summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:50 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:50 -0800
commit8c2158a5ebb88e226c23b66ff95910158a2727df (patch)
tree4b7f7a7a6cdf096d4248c618318ffc2371b0a446
parent1f5bbf66d14caf6c8e7fb594fd1203601f588e93 (diff)
downloadandroid_packages_apps_Email-8c2158a5ebb88e226c23b66ff95910158a2727df.tar.gz
android_packages_apps_Email-8c2158a5ebb88e226c23b66ff95910158a2727df.tar.bz2
android_packages_apps_Email-8c2158a5ebb88e226c23b66ff95910158a2727df.zip
auto import from //depot/cupcake/@135843
-rw-r--r--Android.mk27
-rw-r--r--AndroidManifest.xml163
-rw-r--r--MODULE_LICENSE_APACHE20
-rw-r--r--NOTICE190
-rw-r--r--assets/empty.html4
-rw-r--r--assets/loading.gifbin1969 -> 0 bytes
-rw-r--r--assets/loading.html17
-rw-r--r--assets/test.html18
-rw-r--r--docs/NOTES0
-rw-r--r--docs/TESTS23
-rw-r--r--docs/TODO27
-rw-r--r--images/Android Buttons.ai941
-rw-r--r--images/Android.ai3156
-rw-r--r--res/drawable/appointment_indicator_leftside_1.9.pngbin3000 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_10.9.pngbin3000 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_11.9.pngbin3006 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_12.9.pngbin2995 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_13.9.pngbin2992 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_14.9.pngbin2993 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_15.9.pngbin2993 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_16.9.pngbin2997 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_17.9.pngbin3003 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_18.9.pngbin3001 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_19.9.pngbin3002 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_2.9.pngbin2997 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_20.9.pngbin2997 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_21.9.pngbin2999 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_3.9.pngbin2996 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_4.9.pngbin2999 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_5.9.pngbin3003 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_6.9.pngbin2999 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_7.9.pngbin3000 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_8.9.pngbin3007 -> 0 bytes
-rw-r--r--res/drawable/appointment_indicator_leftside_9.9.pngbin3002 -> 0 bytes
-rw-r--r--res/drawable/attached_image_placeholder.pngbin2100 -> 0 bytes
-rw-r--r--res/drawable/button_indicator_next.pngbin842 -> 0 bytes
-rw-r--r--res/drawable/divider_horizontal_email.9.pngbin436 -> 0 bytes
-rw-r--r--res/drawable/email_quoted_bar.9.pngbin294 -> 0 bytes
-rw-r--r--res/drawable/expander_ic_folder.xml21
-rw-r--r--res/drawable/expander_ic_folder_maximized.9.pngbin1212 -> 0 bytes
-rw-r--r--res/drawable/expander_ic_folder_minimized.9.pngbin1247 -> 0 bytes
-rw-r--r--res/drawable/folder_message_list_child_background.xml26
-rw-r--r--res/drawable/ic_email_attachment.pngbin855 -> 0 bytes
-rw-r--r--res/drawable/ic_email_attachment_small.pngbin713 -> 0 bytes
-rw-r--r--res/drawable/ic_email_thread_open_top_default.9.pngbin706 -> 0 bytes
-rw-r--r--res/drawable/ic_menu_forward_mail.pngbin1739 -> 0 bytes
-rw-r--r--res/drawable/ic_menu_reply.pngbin2441 -> 0 bytes
-rw-r--r--res/drawable/ic_menu_reply_all.pngbin2489 -> 0 bytes
-rw-r--r--res/drawable/ic_menu_save_draft.pngbin2247 -> 0 bytes
-rw-r--r--res/drawable/ic_mms_attachment_small.pngbin1113 -> 0 bytes
-rw-r--r--res/drawable/icon.pngbin3458 -> 0 bytes
-rw-r--r--res/drawable/stat_notify_email_generic.pngbin986 -> 0 bytes
-rw-r--r--res/drawable/text_box.9.pngbin652 -> 0 bytes
-rwxr-xr-xres/drawable/text_box_light.9.pngbin659 -> 0 bytes
-rw-r--r--res/layout-land/message_view.xml67
-rw-r--r--res/layout/account_setup_account_type.xml45
-rw-r--r--res/layout/account_setup_basics.xml81
-rw-r--r--res/layout/account_setup_check_settings.xml54
-rw-r--r--res/layout/account_setup_incoming.xml131
-rw-r--r--res/layout/account_setup_names.xml67
-rw-r--r--res/layout/account_setup_options.xml60
-rw-r--r--res/layout/account_setup_outgoing.xml112
-rw-r--r--res/layout/accounts.xml56
-rw-r--r--res/layout/accounts_item.xml59
-rw-r--r--res/layout/debug.xml40
-rw-r--r--res/layout/folder_message_list_child.xml64
-rw-r--r--res/layout/folder_message_list_child_footer.xml38
-rw-r--r--res/layout/folder_message_list_group.xml60
-rw-r--r--res/layout/message_compose.xml140
-rw-r--r--res/layout/message_compose_attachment.xml51
-rw-r--r--res/layout/message_view.xml88
-rw-r--r--res/layout/message_view_attachment.xml96
-rw-r--r--res/layout/message_view_header.xml157
-rw-r--r--res/layout/recipient_dropdown_item.xml43
-rw-r--r--res/menu/accounts_context.xml24
-rw-r--r--res/menu/accounts_option.xml41
-rw-r--r--res/menu/debug_option.xml20
-rw-r--r--res/menu/folder_message_list_context.xml42
-rw-r--r--res/menu/folder_message_list_option.xml47
-rw-r--r--res/menu/message_compose_option.xml48
-rw-r--r--res/menu/message_view_option.xml48
-rw-r--r--res/values-cs/strings.xml172
-rw-r--r--res/values-de/strings.xml172
-rw-r--r--res/values-es/strings.xml172
-rw-r--r--res/values-fr/strings.xml172
-rw-r--r--res/values-it/strings.xml172
-rw-r--r--res/values-ja/strings.xml172
-rw-r--r--res/values-ko/strings.xml172
-rw-r--r--res/values-nb/strings.xml172
-rw-r--r--res/values-nl/strings.xml172
-rw-r--r--res/values-pl/strings.xml172
-rw-r--r--res/values-ru/strings.xml172
-rw-r--r--res/values-zh-rCN/strings.xml172
-rw-r--r--res/values-zh-rTW/strings.xml172
-rw-r--r--res/values/arrays.xml42
-rw-r--r--res/values/build_number.xml19
-rw-r--r--res/values/colors.xml19
-rw-r--r--res/values/dimensions.xml19
-rw-r--r--res/values/strings.xml366
-rw-r--r--res/xml/account_settings_preferences.xml90
-rw-r--r--res/xml/providers.xml263
-rw-r--r--res/xml/providers_product.xml17
-rw-r--r--src/com/android/email/Account.java387
-rw-r--r--src/com/android/email/Email.java190
-rw-r--r--src/com/android/email/EmailAddressAdapter.java88
-rw-r--r--src/com/android/email/EmailAddressValidator.java33
-rw-r--r--src/com/android/email/FixedLengthInputStream.java75
-rw-r--r--src/com/android/email/MessagingController.java1479
-rw-r--r--src/com/android/email/MessagingListener.java146
-rw-r--r--src/com/android/email/PeekableInputStream.java79
-rw-r--r--src/com/android/email/Preferences.java159
-rw-r--r--src/com/android/email/Utility.java224
-rw-r--r--src/com/android/email/activity/AccountShortcutPicker.java201
-rw-r--r--src/com/android/email/activity/Accounts.java322
-rw-r--r--src/com/android/email/activity/Debug.java88
-rw-r--r--src/com/android/email/activity/FolderMessageList.java1350
-rw-r--r--src/com/android/email/activity/MessageCompose.java1282
-rw-r--r--src/com/android/email/activity/MessageView.java950
-rw-r--r--src/com/android/email/activity/ProgressListener.java51
-rw-r--r--src/com/android/email/activity/Welcome.java51
-rw-r--r--src/com/android/email/activity/setup/AccountSettings.java197
-rw-r--r--src/com/android/email/activity/setup/AccountSetupAccountType.java112
-rw-r--r--src/com/android/email/activity/setup/AccountSetupBasics.java447
-rw-r--r--src/com/android/email/activity/setup/AccountSetupCheckSettings.java227
-rw-r--r--src/com/android/email/activity/setup/AccountSetupIncoming.java364
-rw-r--r--src/com/android/email/activity/setup/AccountSetupNames.java124
-rw-r--r--src/com/android/email/activity/setup/AccountSetupOptions.java122
-rw-r--r--src/com/android/email/activity/setup/AccountSetupOutgoing.java308
-rw-r--r--src/com/android/email/activity/setup/SpinnerOption.java45
-rw-r--r--src/com/android/email/codec/binary/Base64.java801
-rw-r--r--src/com/android/email/codec/binary/Base64OutputStream.java179
-rw-r--r--src/com/android/email/mail/Address.java236
-rw-r--r--src/com/android/email/mail/AuthenticationFailedException.java29
-rw-r--r--src/com/android/email/mail/Body.java26
-rw-r--r--src/com/android/email/mail/BodyPart.java25
-rw-r--r--src/com/android/email/mail/CertificateValidationException.java29
-rw-r--r--src/com/android/email/mail/FetchProfile.java72
-rw-r--r--src/com/android/email/mail/Flag.java63
-rw-r--r--src/com/android/email/mail/Folder.java112
-rw-r--r--src/com/android/email/mail/Message.java133
-rw-r--r--src/com/android/email/mail/MessageDateComparator.java34
-rw-r--r--src/com/android/email/mail/MessageRetrievalListener.java23
-rw-r--r--src/com/android/email/mail/MessagingException.java81
-rw-r--r--src/com/android/email/mail/Multipart.java63
-rw-r--r--src/com/android/email/mail/NoSuchProviderException.java29
-rw-r--r--src/com/android/email/mail/Part.java46
-rw-r--r--src/com/android/email/mail/Sender.java37
-rw-r--r--src/com/android/email/mail/Store.java96
-rw-r--r--src/com/android/email/mail/Transport.java158
-rw-r--r--src/com/android/email/mail/internet/BinaryTempFileBody.java93
-rw-r--r--src/com/android/email/mail/internet/MimeBodyPart.java136
-rw-r--r--src/com/android/email/mail/internet/MimeHeader.java120
-rw-r--r--src/com/android/email/mail/internet/MimeMessage.java446
-rw-r--r--src/com/android/email/mail/internet/MimeMultipart.java106
-rw-r--r--src/com/android/email/mail/internet/MimeUtility.java325
-rw-r--r--src/com/android/email/mail/internet/TextBody.java62
-rw-r--r--src/com/android/email/mail/store/ImapResponseParser.java451
-rw-r--r--src/com/android/email/mail/store/ImapStore.java1272
-rw-r--r--src/com/android/email/mail/store/LocalStore.java1194
-rw-r--r--src/com/android/email/mail/store/Pop3Store.java951
-rw-r--r--src/com/android/email/mail/store/TrustManagerFactory.java110
-rw-r--r--src/com/android/email/mail/transport/CountingOutputStream.java40
-rw-r--r--src/com/android/email/mail/transport/EOLConvertingOutputStream.java49
-rw-r--r--src/com/android/email/mail/transport/MailTransport.java308
-rw-r--r--src/com/android/email/mail/transport/SmtpSender.java332
-rw-r--r--src/com/android/email/mail/transport/StatusOutputStream.java45
-rw-r--r--src/com/android/email/provider/AttachmentProvider.java288
-rw-r--r--src/com/android/email/service/BootReceiver.java37
-rw-r--r--src/com/android/email/service/MailService.java241
-rw-r--r--src/com/beetstra/jutf7/Base64Util.java117
-rw-r--r--src/com/beetstra/jutf7/CharsetProvider.java90
-rw-r--r--src/com/beetstra/jutf7/ModifiedUTF7Charset.java57
-rw-r--r--src/com/beetstra/jutf7/UTF7Charset.java75
-rw-r--r--src/com/beetstra/jutf7/UTF7StyleCharset.java117
-rw-r--r--src/com/beetstra/jutf7/UTF7StyleCharsetDecoder.java195
-rw-r--r--src/com/beetstra/jutf7/UTF7StyleCharsetEncoder.java217
-rw-r--r--src/org/apache/commons/io/CopyUtils.java332
-rw-r--r--src/org/apache/commons/io/DirectoryWalker.java620
-rw-r--r--src/org/apache/commons/io/EndianUtils.java489
-rw-r--r--src/org/apache/commons/io/FileCleaner.java154
-rw-r--r--src/org/apache/commons/io/FileCleaningTracker.java258
-rw-r--r--src/org/apache/commons/io/FileDeleteStrategy.java156
-rw-r--r--src/org/apache/commons/io/FileSystemUtils.java457
-rw-r--r--src/org/apache/commons/io/FileUtils.java1890
-rw-r--r--src/org/apache/commons/io/FilenameUtils.java1260
-rw-r--r--src/org/apache/commons/io/HexDump.java149
-rw-r--r--src/org/apache/commons/io/IOCase.java238
-rw-r--r--src/org/apache/commons/io/IOExceptionWithCause.java69
-rw-r--r--src/org/apache/commons/io/IOUtils.java1274
-rw-r--r--src/org/apache/commons/io/LineIterator.java181
-rw-r--r--src/org/apache/commons/io/comparator/DefaultFileComparator.java68
-rw-r--r--src/org/apache/commons/io/comparator/ExtensionFileComparator.java112
-rw-r--r--src/org/apache/commons/io/comparator/LastModifiedFileComparator.java79
-rw-r--r--src/org/apache/commons/io/comparator/NameFileComparator.java106
-rw-r--r--src/org/apache/commons/io/comparator/PathFileComparator.java107
-rw-r--r--src/org/apache/commons/io/comparator/ReverseComparator.java57
-rw-r--r--src/org/apache/commons/io/comparator/SizeFileComparator.java132
-rw-r--r--src/org/apache/commons/io/comparator/package.html25
-rw-r--r--src/org/apache/commons/io/filefilter/AbstractFileFilter.java67
-rw-r--r--src/org/apache/commons/io/filefilter/AgeFileFilter.java150
-rw-r--r--src/org/apache/commons/io/filefilter/AndFileFilter.java167
-rw-r--r--src/org/apache/commons/io/filefilter/CanReadFileFilter.java92
-rw-r--r--src/org/apache/commons/io/filefilter/CanWriteFileFilter.java80
-rw-r--r--src/org/apache/commons/io/filefilter/ConditionalFileFilter.java67
-rw-r--r--src/org/apache/commons/io/filefilter/DelegateFileFilter.java104
-rw-r--r--src/org/apache/commons/io/filefilter/DirectoryFileFilter.java73
-rw-r--r--src/org/apache/commons/io/filefilter/EmptyFileFilter.java84
-rw-r--r--src/org/apache/commons/io/filefilter/FalseFileFilter.java72
-rw-r--r--src/org/apache/commons/io/filefilter/FileFileFilter.java60
-rw-r--r--src/org/apache/commons/io/filefilter/FileFilterUtils.java361
-rw-r--r--src/org/apache/commons/io/filefilter/HiddenFileFilter.java76
-rw-r--r--src/org/apache/commons/io/filefilter/IOFileFilter.java55
-rw-r--r--src/org/apache/commons/io/filefilter/NameFileFilter.java191
-rw-r--r--src/org/apache/commons/io/filefilter/NotFileFilter.java78
-rw-r--r--src/org/apache/commons/io/filefilter/OrFileFilter.java161
-rw-r--r--src/org/apache/commons/io/filefilter/PrefixFileFilter.java197
-rw-r--r--src/org/apache/commons/io/filefilter/RegexFileFilter.java122
-rw-r--r--src/org/apache/commons/io/filefilter/SizeFileFilter.java103
-rw-r--r--src/org/apache/commons/io/filefilter/SuffixFileFilter.java198
-rw-r--r--src/org/apache/commons/io/filefilter/TrueFileFilter.java72
-rw-r--r--src/org/apache/commons/io/filefilter/WildcardFileFilter.java196
-rw-r--r--src/org/apache/commons/io/filefilter/WildcardFilter.java140
-rw-r--r--src/org/apache/commons/io/filefilter/package.html143
-rw-r--r--src/org/apache/commons/io/input/AutoCloseInputStream.java129
-rw-r--r--src/org/apache/commons/io/input/CharSequenceReader.java155
-rw-r--r--src/org/apache/commons/io/input/ClassLoaderObjectInputStream.java77
-rw-r--r--src/org/apache/commons/io/input/CloseShieldInputStream.java52
-rw-r--r--src/org/apache/commons/io/input/ClosedInputStream.java48
-rw-r--r--src/org/apache/commons/io/input/CountingInputStream.java175
-rw-r--r--src/org/apache/commons/io/input/DemuxInputStream.java91
-rw-r--r--src/org/apache/commons/io/input/NullInputStream.java329
-rw-r--r--src/org/apache/commons/io/input/NullReader.java313
-rw-r--r--src/org/apache/commons/io/input/ProxyInputStream.java129
-rw-r--r--src/org/apache/commons/io/input/ProxyReader.java130
-rw-r--r--src/org/apache/commons/io/input/SwappedDataInputStream.java251
-rw-r--r--src/org/apache/commons/io/input/TeeInputStream.java147
-rw-r--r--src/org/apache/commons/io/input/package.html25
-rw-r--r--src/org/apache/commons/io/output/ByteArrayOutputStream.java308
-rw-r--r--src/org/apache/commons/io/output/CloseShieldOutputStream.java52
-rw-r--r--src/org/apache/commons/io/output/ClosedOutputStream.java50
-rw-r--r--src/org/apache/commons/io/output/CountingOutputStream.java154
-rw-r--r--src/org/apache/commons/io/output/DeferredFileOutputStream.java269
-rw-r--r--src/org/apache/commons/io/output/DemuxOutputStream.java102
-rw-r--r--src/org/apache/commons/io/output/FileWriterWithEncoding.java324
-rw-r--r--src/org/apache/commons/io/output/LockableFileWriter.java333
-rw-r--r--src/org/apache/commons/io/output/NullOutputStream.java65
-rw-r--r--src/org/apache/commons/io/output/NullWriter.java96
-rw-r--r--src/org/apache/commons/io/output/ProxyOutputStream.java89
-rw-r--r--src/org/apache/commons/io/output/ProxyWriter.java111
-rw-r--r--src/org/apache/commons/io/output/TeeOutputStream.java94
-rw-r--r--src/org/apache/commons/io/output/ThresholdingOutputStream.java257
-rw-r--r--src/org/apache/commons/io/output/package.html25
-rw-r--r--src/org/apache/commons/io/overview.html32
-rw-r--r--src/org/apache/commons/io/package.html47
-rw-r--r--src/org/apache/james/mime4j/AbstractContentHandler.java113
-rw-r--r--src/org/apache/james/mime4j/BodyDescriptor.java410
-rw-r--r--src/org/apache/james/mime4j/CloseShieldInputStream.java129
-rw-r--r--src/org/apache/james/mime4j/ContentHandler.java177
-rw-r--r--src/org/apache/james/mime4j/EOLConvertingInputStream.java108
-rw-r--r--src/org/apache/james/mime4j/MimeBoundaryInputStream.java184
-rw-r--r--src/org/apache/james/mime4j/MimeStreamParser.java320
-rw-r--r--src/org/apache/james/mime4j/RootInputStream.java111
-rw-r--r--src/org/apache/james/mime4j/SimpleContentHandler.java100
-rw-r--r--src/org/apache/james/mime4j/decoder/Base64InputStream.java146
-rw-r--r--src/org/apache/james/mime4j/decoder/ByteQueue.java62
-rw-r--r--src/org/apache/james/mime4j/decoder/DecoderUtil.java276
-rw-r--r--src/org/apache/james/mime4j/decoder/QuotedPrintableInputStream.java227
-rw-r--r--src/org/apache/james/mime4j/decoder/UnboundedFifoByteBuffer.java272
-rw-r--r--src/org/apache/james/mime4j/field/AddressListField.java63
-rw-r--r--src/org/apache/james/mime4j/field/ContentTransferEncodingField.java88
-rw-r--r--src/org/apache/james/mime4j/field/ContentTypeField.java256
-rw-r--r--src/org/apache/james/mime4j/field/DateTimeField.java65
-rw-r--r--src/org/apache/james/mime4j/field/DefaultFieldParser.java45
-rw-r--r--src/org/apache/james/mime4j/field/DelegatingFieldParser.java47
-rw-r--r--src/org/apache/james/mime4j/field/Field.java192
-rw-r--r--src/org/apache/james/mime4j/field/FieldParser.java21
-rw-r--r--src/org/apache/james/mime4j/field/MailboxField.java68
-rw-r--r--src/org/apache/james/mime4j/field/MailboxListField.java65
-rw-r--r--src/org/apache/james/mime4j/field/UnstructuredField.java49
-rw-r--r--src/org/apache/james/mime4j/field/address/Address.java52
-rw-r--r--src/org/apache/james/mime4j/field/address/AddressList.java140
-rw-r--r--src/org/apache/james/mime4j/field/address/Builder.java244
-rw-r--r--src/org/apache/james/mime4j/field/address/DomainList.java76
-rw-r--r--src/org/apache/james/mime4j/field/address/Group.java73
-rw-r--r--src/org/apache/james/mime4j/field/address/Mailbox.java119
-rw-r--r--src/org/apache/james/mime4j/field/address/MailboxList.java71
-rw-r--r--src/org/apache/james/mime4j/field/address/NamedMailbox.java70
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/ASTaddr_spec.java19
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/ASTaddress.java19
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/ASTaddress_list.java19
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/ASTangle_addr.java19
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/ASTdomain.java19
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/ASTgroup_body.java19
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/ASTlocal_part.java19
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/ASTmailbox.java19
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/ASTname_addr.java19
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/ASTphrase.java19
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/ASTroute.java19
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/AddressListParser.java977
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/AddressListParser.jj595
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/AddressListParserConstants.java76
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/AddressListParserTokenManager.java1009
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/AddressListParserTreeConstants.java35
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/AddressListParserVisitor.java19
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/BaseNode.java30
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/JJTAddressListParserState.java123
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/Node.java37
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/ParseException.java207
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/SimpleCharStream.java454
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/SimpleNode.java87
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/Token.java96
-rw-r--r--src/org/apache/james/mime4j/field/address/parser/TokenMgrError.java148
-rw-r--r--src/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParser.java267
-rw-r--r--src/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParserConstants.java62
-rw-r--r--src/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParserTokenManager.java877
-rw-r--r--src/org/apache/james/mime4j/field/contenttype/parser/ParseException.java207
-rw-r--r--src/org/apache/james/mime4j/field/contenttype/parser/SimpleCharStream.java454
-rw-r--r--src/org/apache/james/mime4j/field/contenttype/parser/Token.java96
-rw-r--r--src/org/apache/james/mime4j/field/contenttype/parser/TokenMgrError.java148
-rw-r--r--src/org/apache/james/mime4j/field/datetime/DateTime.java127
-rw-r--r--src/org/apache/james/mime4j/field/datetime/parser/DateTimeParser.java570
-rw-r--r--src/org/apache/james/mime4j/field/datetime/parser/DateTimeParserConstants.java86
-rw-r--r--src/org/apache/james/mime4j/field/datetime/parser/DateTimeParserTokenManager.java882
-rw-r--r--src/org/apache/james/mime4j/field/datetime/parser/ParseException.java207
-rw-r--r--src/org/apache/james/mime4j/field/datetime/parser/SimpleCharStream.java454
-rw-r--r--src/org/apache/james/mime4j/field/datetime/parser/Token.java96
-rw-r--r--src/org/apache/james/mime4j/field/datetime/parser/TokenMgrError.java148
-rw-r--r--src/org/apache/james/mime4j/message/AbstractBody.java47
-rw-r--r--src/org/apache/james/mime4j/message/BinaryBody.java42
-rw-r--r--src/org/apache/james/mime4j/message/Body.java54
-rw-r--r--src/org/apache/james/mime4j/message/BodyPart.java42
-rw-r--r--src/org/apache/james/mime4j/message/Entity.java170
-rw-r--r--src/org/apache/james/mime4j/message/Header.java155
-rw-r--r--src/org/apache/james/mime4j/message/MemoryBinaryBody.java90
-rw-r--r--src/org/apache/james/mime4j/message/MemoryTextBody.java116
-rw-r--r--src/org/apache/james/mime4j/message/Message.java256
-rw-r--r--src/org/apache/james/mime4j/message/Multipart.java203
-rw-r--r--src/org/apache/james/mime4j/message/TempFileBinaryBody.java89
-rw-r--r--src/org/apache/james/mime4j/message/TempFileTextBody.java115
-rw-r--r--src/org/apache/james/mime4j/message/TextBody.java42
-rw-r--r--src/org/apache/james/mime4j/util/CharsetUtil.java1178
-rw-r--r--src/org/apache/james/mime4j/util/PartialInputStream.java63
-rw-r--r--src/org/apache/james/mime4j/util/PositionInputStream.java87
-rw-r--r--src/org/apache/james/mime4j/util/SimpleTempStorage.java236
-rw-r--r--src/org/apache/james/mime4j/util/TempFile.java84
-rw-r--r--src/org/apache/james/mime4j/util/TempPath.java73
-rw-r--r--src/org/apache/james/mime4j/util/TempStorage.java70
-rw-r--r--tests/Android.mk37
-rw-r--r--tests/AndroidManifest.xml37
-rw-r--r--tests/src/com/android/email/AccountUnitTests.java148
-rw-r--r--tests/src/com/android/email/PreferencesUnitTests.java101
-rw-r--r--tests/src/com/android/email/SmallTests.java40
-rw-r--r--tests/src/com/android/email/UtilityUnitTests.java45
-rw-r--r--tests/src/com/android/email/activity/FolderMessageListUnitTests.java166
-rw-r--r--tests/src/com/android/email/activity/MessageComposeInstrumentationTests.java422
-rw-r--r--tests/src/com/android/email/activity/MessageViewTests.java148
-rw-r--r--tests/src/com/android/email/activity/setup/AccountSetupIncomingTests.java151
-rw-r--r--tests/src/com/android/email/activity/setup/AccountSetupNamesTests.java83
-rw-r--r--tests/src/com/android/email/activity/setup/AccountSetupOutgoingTests.java148
-rw-r--r--tests/src/com/android/email/codec/binary/Base64Test.java162
-rw-r--r--tests/src/com/android/email/mail/AddressUnitTests.java80
-rw-r--r--tests/src/com/android/email/mail/internet/MimeMessageTest.java74
-rw-r--r--tests/src/com/android/email/mail/internet/MimeUtilityTest.java114
-rw-r--r--tests/src/com/android/email/mail/store/ImapStoreUnitTests.java154
-rw-r--r--tests/src/com/android/email/mail/store/Pop3StoreUnitTests.java676
-rw-r--r--tests/src/com/android/email/mail/transport/MailTransportUnitTests.java57
-rw-r--r--tests/src/com/android/email/mail/transport/MockTransport.java333
-rw-r--r--tests/src/com/android/email/mail/transport/SmtpSenderUnitTests.java145
368 files changed, 0 insertions, 63846 deletions
diff --git a/Android.mk b/Android.mk
deleted file mode 100644
index be1d7198c..000000000
--- a/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2008, The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := eng development
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := Email
-
-include $(BUILD_PACKAGE)
-
-# additionally, build unit tests in a separate .apk
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
deleted file mode 100644
index 025d49501..000000000
--- a/AndroidManifest.xml
+++ /dev/null
@@ -1,163 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.email">
- <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
- <uses-permission android:name="android.permission.READ_CONTACTS"/>
- <uses-permission android:name="android.permission.READ_OWNER_DATA"/>
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
- <uses-permission android:name="android.permission.INTERNET"/>
- <uses-permission android:name="android.permission.VIBRATE"/>
- <permission android:name="com.android.email.permission.READ_ATTACHMENT"
- android:permissionGroup="android.permission-group.MESSAGES"
- android:protectionLevel="dangerous"
- android:label="@string/read_attachment_label"
- android:description="@string/read_attachment_desc"/>
- <uses-permission android:name="com.android.email.permission.READ_ATTACHMENT"/>
- <application android:icon="@drawable/icon" android:label="@string/app_name"
- android:name="Email">
- <activity android:name=".activity.Welcome">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
-
- <activity
- android:name=".activity.setup.AccountSetupBasics"
- android:label="@string/account_setup_basics_title"
- >
- </activity>
- <activity
- android:name=".activity.setup.AccountSetupAccountType"
- android:label="@string/account_setup_account_type_title"
- >
- </activity>
- <activity
- android:name=".activity.setup.AccountSetupIncoming"
- android:label="@string/account_setup_incoming_title"
- >
- </activity>
- <activity
- android:name=".activity.setup.AccountSetupOutgoing"
- android:label="@string/account_setup_outgoing_title"
- >
- </activity>
- <activity
- android:name=".activity.setup.AccountSetupOptions"
- android:label="@string/account_setup_options_title"
- >
- </activity>
- <activity
- android:name=".activity.setup.AccountSetupNames"
- android:label="@string/account_setup_names_title"
- >
- </activity>
- <!-- XXX Note: this activity is hacked to ignore config changes,
- since it doesn't currently handle them correctly in code. -->
- <activity
- android:name=".activity.setup.AccountSetupCheckSettings"
- android:label="@string/account_setup_check_settings_title"
- android:configChanges="keyboardHidden|orientation"
- >
- </activity>
- <activity
- android:name=".activity.setup.AccountSettings"
- android:label="@string/account_settings_action"
- >
- </activity>
-
- <activity
- android:name=".activity.Debug"
- android:label="@string/debug_title">
- </activity>
- <activity
- android:name=".activity.Accounts"
- android:label="@string/accounts_title"
- android:launchMode="singleTop" >
- </activity>
-
- <activity
- android:name=".activity.AccountShortcutPicker"
- android:label="@string/app_name"
- android:enabled="false"
- >
- <intent-filter>
- <action android:name="android.intent.action.CREATE_SHORTCUT" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
-
- <activity
- android:name=".activity.FolderMessageList">
- <intent-filter>
- <!-- This action is only to allow an entry point for launcher shortcuts -->
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </activity>
- <activity
- android:name=".activity.MessageView"
- android:theme="@android:style/Theme.NoTitleBar" >
- </activity>
- <activity
- android:name=".activity.MessageCompose"
- android:label="@string/app_name"
- android:enabled="false"
- >
- <intent-filter>
- <action android:name="android.intent.action.VIEW" />
- <action android:name="android.intent.action.SENDTO" />
- <data android:scheme="mailto" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.BROWSABLE" />
- </intent-filter>
- <intent-filter android:label="@string/app_name">
- <action android:name="android.intent.action.SEND" />
- <data android:mimeType="text/plain" />
- <data android:mimeType="image/*" />
- <data android:mimeType="video/*" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
- <receiver android:name=".service.BootReceiver"
- android:enabled="false"
- >
- <intent-filter>
- <action android:name="android.intent.action.BOOT_COMPLETED" />
- </intent-filter>
- <intent-filter>
- <action android:name="android.intent.action.DEVICE_STORAGE_LOW" />
- </intent-filter>
- <intent-filter>
- <action android:name="android.intent.action.DEVICE_STORAGE_OK" />
- </intent-filter>
- </receiver>
- <service
- android:name=".service.MailService"
- android:enabled="false"
- >
- </service>
- <provider
- android:name=".provider.AttachmentProvider"
- android:authorities="com.android.email.attachmentprovider"
- android:multiprocess="true"
- android:grantUriPermissions="true"
- android:readPermission="com.android.email.permission.READ_ATTACHMENT"
- />
- </application>
-</manifest>
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29bb..000000000
--- a/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/NOTICE b/NOTICE
deleted file mode 100644
index c5b1efa7a..000000000
--- a/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
- Copyright (c) 2005-2008, The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
diff --git a/assets/empty.html b/assets/empty.html
deleted file mode 100644
index c044e9195..000000000
--- a/assets/empty.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<html>
- <body bgcolor="white">
- </body>
-</html> \ No newline at end of file
diff --git a/assets/loading.gif b/assets/loading.gif
deleted file mode 100644
index ab9982483..000000000
--- a/assets/loading.gif
+++ /dev/null
Binary files differ
diff --git a/assets/loading.html b/assets/loading.html
deleted file mode 100644
index 0cc9cecc3..000000000
--- a/assets/loading.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<html>
- <body bgcolor="white">
- <table width="100%" height="100%">
- <tr>
- <td align="center" valign="center">
- <font color="gray">Loading...</font>
- <br/>
- <br/>
- <br/>
- <br/>
- <br/>
- <img src="loading.gif">
- </td>
- </tr>
- </table>
- </body>
-</html> \ No newline at end of file
diff --git a/assets/test.html b/assets/test.html
deleted file mode 100644
index 09d6f119e..000000000
--- a/assets/test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<html>
- <body>
-Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Phasellus dui dui, luctus sit amet, hendrerit ac, blandit quis, diam. Duis libero velit, elementum id, mattis ut, fermentum aliquet, tortor. Maecenas tincidunt egestas pede. Integer sagittis ipsum ut lorem. Morbi egestas egestas sapien. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Duis eget erat ac sem iaculis sollicitudin. Maecenas in velit id mauris cursus tincidunt. Sed ultrices elit in sapien ullamcorper imperdiet. Nunc viverra, lacus id varius elementum, nisl turpis lacinia tellus, sit amet viverra neque odio quis nisl. Quisque facilisis, ipsum non vulputate malesuada, leo augue elementum tortor, nec eleifend tellus lectus non massa.
-<br/><br/>
-Maecenas pulvinar rutrum risus. Phasellus mattis arcu sit amet neque. Aliquam sed quam at nulla laoreet pretium. Proin elit. Integer ullamcorper dolor a pede. Nam lobortis quam ut mauris. Pellentesque non mauris ut lacus hendrerit iaculis. In volutpat nulla et turpis. Fusce mollis. Aliquam sit amet tortor fermentum orci lacinia convallis. Donec tincidunt tortor sed erat sollicitudin gravida. In hac habitasse platea dictumst. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed pulvinar arcu consectetuer dolor. Nunc luctus aliquam leo. In hac habitasse platea dictumst. Praesent et mi sit amet ligula blandit hendrerit. Nam aliquam tincidunt est. Aliquam erat volutpat.
-<br/><br/>
-Curabitur augue. Fusce pulvinar nisi vitae diam. Donec dictum. Sed suscipit convallis magna. Ut hendrerit tortor in mauris. In at diam. Maecenas commodo. Aliquam erat volutpat. Nunc odio eros, vestibulum at, sodales id, congue et, risus. Curabitur feugiat blandit lacus. Nulla gravida placerat enim. Nunc turpis. Praesent malesuada.
-<br/><br/>
-Aenean quis erat. Vivamus non ipsum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed metus magna, porta eu, ultricies vitae, vulputate et, urna. Sed pulvinar, massa at ultricies rhoncus, nunc eros dapibus felis, quis congue risus orci rhoncus nibh. Pellentesque quam ante, laoreet vitae, iaculis a, gravida in, nibh. In hac habitasse platea dictumst. Aliquam erat volutpat. Suspendisse augue neque, posuere eu, sollicitudin quis, sagittis et, massa. Maecenas varius sem sodales ipsum. Donec congue mi nec orci. Nam pede ipsum, varius sed, condimentum ac, rhoncus non, lorem. Integer vestibulum, neque vitae ornare euismod, mauris turpis congue massa, non venenatis arcu lorem eget metus. Sed sollicitudin, enim aliquam pharetra cursus, neque augue bibendum leo, vitae ullamcorper ante felis nec massa. Maecenas vitae urna. Proin tincidunt, urna eu sodales vulputate, nisl tellus pretium ligula, ut venenatis metus nulla eu lectus. Integer urna purus, sagittis ut, posuere sed, sagittis non, mauris. Nunc eros risus, lacinia sit amet, dictum in, faucibus quis, urna. Fusce dictum mattis enim. Vivamus luctus sagittis felis.
-<br/><br/>
-Fusce pulvinar, erat a facilisis congue, lacus libero imperdiet dui, nec luctus justo neque sit amet mauris. Praesent sodales. Sed sed nisl a arcu tempus placerat. Duis sagittis risus. Aliquam tristique. Ut a mi. Integer volutpat, turpis vitae lobortis blandit, lorem sapien suscipit arcu, sit amet dignissim felis mauris vitae ipsum. Sed elit. Mauris elementum, pede nec accumsan pretium, leo metus fringilla erat, at feugiat turpis arcu pretium urna. Morbi lorem tellus, commodo sed, convallis id, suscipit sed, leo. Donec egestas ultricies tellus. Curabitur sapien orci, interdum nec, molestie at, pharetra eu, magna. Duis pharetra orci sed felis posuere malesuada. Donec nec nisi non urna ultricies porttitor. Maecenas lectus. Sed dignissim malesuada justo. Nunc rutrum consectetuer nunc.
-
- <img src="cid:23978198273">
- more text
- <img src="cid:12371982371">
- more text
- </body>
-</html> \ No newline at end of file
diff --git a/docs/NOTES b/docs/NOTES
deleted file mode 100644
index e69de29bb..000000000
--- a/docs/NOTES
+++ /dev/null
diff --git a/docs/TESTS b/docs/TESTS
deleted file mode 100644
index b89e882a1..000000000
--- a/docs/TESTS
+++ /dev/null
@@ -1,23 +0,0 @@
-Some simple functional tests
---
-
-Compose a message
- Attach an image to the message
- Save the message as a draft
- Reopen the draft
- * Is the attachment still there?
- Send the message.
- * Does the received message have the correct attachment?
-
-Check delete functionality on POP and IMAP account.
-
-Check delete functionality on IMAP with no network connection.
-
-Check save draft functionality on POP and IMAP account.
-
-Check save draft functionality on IMAP with no network connection.
-
-Check sent message functionality on POP and IMAP account.
-
-Check sent functionality on IMAP with no network connection.
- * When the network is brought back does the sent message get uploaded?
diff --git a/docs/TODO b/docs/TODO
deleted file mode 100644
index d504dd434..000000000
--- a/docs/TODO
+++ /dev/null
@@ -1,27 +0,0 @@
-Currently
---
-Need to add NOOP checking to Pop3Store and ImapStore on cached connections.
-
-
-
-
-
-
-
-
-
-
-
-
-In the future
---
-Move attachments to files, instead of storing as blobs in the database. There are tons of ways
-we can make the app perform better with this small change. Primarily, we can do everything
-pertaining to large attachments as streams instead of as large loads into byte arrays.
-
-Get rid of the LocalStore's attachment to Store altogether. Local storage is too complex and
-specific to performance to be bound to the Store API. It needs to be flexible with plenty of helper
-functions to make best use of memory and resources.
-
-Make better use of the abstractions for Body, Part and BodyPart. Proper use of these abstractions
-can completely remove the need for the special headers.
diff --git a/images/Android Buttons.ai b/images/Android Buttons.ai
deleted file mode 100644
index 677ef3a99..000000000
--- a/images/Android Buttons.ai
+++ /dev/null
@@ -1,941 +0,0 @@
-%PDF-1.5 %âãÏÓ
-1 0 obj <</Metadata 103 0 R/Pages 2 0 R/OCProperties<</D<</RBGroups[]/ON[14 0 R 20 0 R 38 0 R 56 0 R 76 0 R 94 0 R]/Order 93 0 R>>/OCGs[14 0 R 20 0 R 38 0 R 56 0 R 76 0 R 94 0 R]>>/Type/Catalog>> endobj 103 0 obj <</Subtype/XML/Length 39699/Type/Metadata>>stream
-<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
-<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.1-c036 46.277092, Fri Feb 23 2007 14:16:18 ">
- <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
- <rdf:Description rdf:about=""
- xmlns:dc="http://purl.org/dc/elements/1.1/">
- <dc:format>application/pdf</dc:format>
- <dc:title>
- <rdf:Alt>
- <rdf:li xml:lang="x-default">Untitled-1</rdf:li>
- </rdf:Alt>
- </dc:title>
- </rdf:Description>
- <rdf:Description rdf:about=""
- xmlns:xap="http://ns.adobe.com/xap/1.0/"
- xmlns:xapGImg="http://ns.adobe.com/xap/1.0/g/img/">
- <xap:CreatorTool>Adobe Illustrator CS3</xap:CreatorTool>
- <xap:CreateDate>2008-05-22T23:46:02-07:00</xap:CreateDate>
- <xap:ModifyDate>2008-05-30T23:55:25-07:00</xap:ModifyDate>
- <xap:MetadataDate>2008-05-30T23:55:25-07:00</xap:MetadataDate>
- <xap:Thumbnails>
- <rdf:Alt>
- <rdf:li rdf:parseType="Resource">
- <xapGImg:width>256</xapGImg:width>
- <xapGImg:height>180</xapGImg:height>
- <xapGImg:format>JPEG</xapGImg:format>
- <xapGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA&#xA;AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK&#xA;DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f&#xA;Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAtAEAAwER&#xA;AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA&#xA;AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB&#xA;UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE&#xA;1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ&#xA;qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy&#xA;obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp&#xA;0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo&#xA;+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8AN8VdirsVdirsVVZ/qNki&#xA;NfSOJZFDpaxAF+JFVLsxAQMNx1NN6UIOKrYLnSbuQRQSSW0zbRrccfTY+HqinEn3WniRiq10dHZH&#xA;BV1JDKdiCNiDiqpb25l5szrFDEOU0714IvSpoCdzsABU4qpHU9CB4AXTj/f1I1/5J1b/AIniqpJH&#xA;EY1nt5BNbOaLIAVIYblXU/ZYV+XgTiqnirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsV&#xA;dirsVdirsVdirsVdiqtYxxy3tvHLtG8iK5/ySwBxVgnmrXfNEetTm20v60JCXlkqRR2Y8k2/lzdd&#xA;n6LS5cfFly8Er5Klltr/AJtkuIkl0X04mdVkkqfhUmhP0DMrL2boYwJjnsgbBXp1y7yCCWT+9kgi&#xA;aTuSeAHI+7ABj885tVeK2sLmHTbS/uvqVjdXU/1u4HYQxRmMn5GRgPniqb/4N/LX/qav+FX+mKpX&#xA;cafo1heahZ6TqH6Rsfqkc/q0AHrCdU7d1R2+/FUvxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Kux&#xA;V2KuxV2KuxV2KuxV2KuxV2KuxV2Ku1Cxg1GU3UcqwXknxXEctQkj93RgDQt1YNQV6HegVUIdCihk&#xA;5XtxGyL/ALpgbm7+3MDgo96kjwxVFTzNNK0jACtAFXZVUCiqo8ABQYq2voS28lpc1EEhDrIoq0br&#xA;UBlBIrsSGFd/mBiqBPl6apK3ds0QP95zYf8ACFRJ/wALiqMjit7S2a2t29VpCGuJ6ceRWtFQHfgK&#xA;k77nuBQYqtxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVXa0eOMSXD&#xA;x26sAyCV1V2B6EJXnQ+NKYq1LaSxx+qCssJPH1onWRK+BZSaH2O+KqOKq0NpNKjSDikSbPNIyxxg&#xA;noOblVqew64quFk7hjBLDcFQSyQyI70G5PAHkQAKkgYqh8VbjjeR1jjUu7kBUUVJJ6AAYqrtYsjc&#xA;JLi2jl6em88QYHpRvi+E+IalMVU57eaBwkq8SQGU9QynoykbMD2IxVTxV2KuxV2KuxV2KuxV2Kux&#xA;V2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KoiyKxtLcugkW1iebg24LLslQeo5stR4YqyryD5B1p9c&#xA;i1bXrOK70+6haUtO0c/JpVDIxRuRrv4Yqkmo+UvMXly+e/vLdYtJurn6vIiOhDRSsSF4KdqAVXwI&#xA;GKpXPE0M0kLfajYo3zU0xVj3nrzZpml6y+mXkzRR2ZaK3iVWYURijSGgPxOylj93QDNlouyc+piZ&#xA;YxYBrmArB/J/nW1s7FU1C9mN+Ji0cjeo7AbcaPvTfOg7a7CyTy8WGERDh6UN9+ivXJ3M0NreFQrX&#xA;cXqOqig5q7RMQB/M0fL6c41VC/1BdM0Sa6DlJZ2aISD7SxIvKalN6tyUbdqjvkZSERZbMOKWSYhH&#xA;6pGg89uvMFs2p2skU7i1QN6yjkATvSq98189VEzBB9PV63TdhZY6XJGcI+Ka4eX39Ga+WNYh1Kxu&#xA;LaNzJBEDJb8gRwkUrzAqOjI2/uBmdjyxmLDzOs0WTTTEMgokWjsscR2KuxV2KuxV2KuxV2KuxV2K&#xA;uxV2KuxV2KuxV2KuxV2KuxV2KuxV2KqtrJEsjJMCYJkaKWm5CuKcgNqlT8Q9xiqZ+UtZuvK+vR3m&#xA;ryXE+lLG8cUsJaWJ6gBeHIqu3gdx3GKpav1+6v31C+kmGmiZriCGdm/fEMSiIhPT+ZugHvQFVSd2&#xA;d2djVmJLHxJxVC6/oy39zJqkVutys37y5XiHeKRt5KihIQtup6b065ZDLOP0kj4qxPyP5MvotPNt&#xA;PbRSyiVneegMaKQKF5GAC9M3HbPag1GbixGQjw13d6s5n9JVit4TyhtkEaPQjluWZt9/idiR7Zo1&#xA;c9ul9p8lgxVZeYlty5AQtQq0ZJ2HMU3O1QPGoUgkGww3UdAu01u05WvpCKolhZeLEtUD4SN8xZ4L&#xA;yRIGwd3pe0xDS5McpS45VX9rK9N006ZbzNNGIrm4X00t6cWROQZncfsluPEA70qTTauSABydLOcp&#xA;G5G1+Fi7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqj44JbLea9FlKw3&#xA;hUuZadRyCCi/JiD7ZrNV2vp8EuGR9XcN2jJqIRNEqc9o8iyXMVwt4q7zOpbmtTSrq4Vqf5QqPfLd&#xA;J2jh1H0S37urLHmjPkUJmc2to7owdGKsNwwNCPpGKr5rq5np60zy8enNi1PvxVTxV2Kq8d/fRRGG&#xA;K5lSI9Y1dgp+gGmKqGKuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Kov&#xA;S6LdGUgEwRyzIDuC8cZZNj1owBI8MxNfmOPBOY5iLXllwxJDNvIflC5h1nTdck1G2m9SNpmtw5ac&#xA;maFtiCPtDn8Wc32R2bKOWGYzibF1e+8f27uFp8JEhKwlXmXy1c6NeXOti+tZ1a6Ym1RyXKyuaoy0&#xA;6cTRsxdZo56bIc8ZxJ47oHfc/i2GTGYHjBHNjN9Atve3FupJWGR4wT1orEb53ALtFHCrsVdirsVd&#xA;irsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVVrO5NtcLLx5qKrIla&#xA;ckdSrrXtyUkZDLjE4mMuRFIkLFFNfLsj6Nr1tq1pGdSt4PUKxxkLLR42T40+JlI5+BHgc4vH2fn0&#xA;WoExA5Ii/p8wR8HWDDLFO6sIW4QfpOfUrxBGJJnnjsmIaRizFgrgfZUV+LlSvbJaPsfLmzHJkjwQ&#xA;4ro8z1pOPTylKyKCXu7O7Ox5MxJYnqSc7V2bWKuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV&#xA;2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2&#xA;KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2K&#xA;uxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ku&#xA;xV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KtqrMwVQ&#xA;WZjRVG5JPYYqzLQvyv1u/VZr5hp8DUIVxymI/wBTbj/sjX2xVlsP5c+TNOjD3zGX/iy5m9Na/wCx&#xA;MYyGTLGAuRAHmyhCUtoi131H8r0PCtgad/VDfjyOYh7T0w/ykPmHIGhz/wAyXybPkryBqYP1RYi5&#xA;r8VrOW/AMy/hmRi1GPJ9Eoy9xBaZ4Zw+qJHvDH9Y/KO5jVpNJuxMB0gnorfQ4+En5gZc1sDvtPvb&#xA;C4a2vIXgnTqjih+Y8R7jFVDFXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXY&#xA;q7FXYqrWVldXt1Ha2sZluJTxjjXqTir1vQPLGh+UtP8A0lqciNegfvLltwhI+xCOtfxOU6jUQwwM&#xA;5mohtw4ZZJcMRZY35g/M3U7tmh0sfUrboJTQzMPnuF+jf3zidf7SZchrF6I9/wDF+z8bvT6TsWEN&#xA;8nql9n7WHT3FxcSGW4leaVuryMWY/Sd85yeSUzciSfN3MYCIoCgp5Fk2rMrBlJDDcEbEHEGuSCLZ&#xA;Lof5g69pjKk0hvrUdYpiSwH+TJuw+mo9s3ei7e1GE0Txx7j+gus1XZOHLuBwy8v1M+WTyz520ooy&#xA;8nQbqaLPAx7g+H4HO40PaOLUx4oHfqOoeW1ejnglUvn0eV+Z/LN9oF/9XuPjherW1wBRXUfqI7jM&#xA;5xUnxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV6x+X/l+20TRn13U&#xA;aJPNGZAzf7qgpUfS/X7hkMuSMImUjUQzhAzkIjmWE+avM93r1+ZHJS0jJFtb9lXxP+Ue+eZ9qdpT&#xA;1WSztAch+Or22h0UcEKH1HmVDQ/Luqa3NJFYxhvSUtJI54oNtl5eLdsq0XZ+XUkjGOXy/BbNVrMe&#xA;AAzPNL7i3nt53gnQxzRkrJGwoQR2OYmTHKEjGQohyITEhY3BWZFk4Ak0G5PQYqmmq+WdZ0u0t7q9&#xA;gMcNyKqepQ9lf+Vqb0/tzO1XZubBCM5ihL7PI9xcTBrcWWRjE7j8bIXS9UvdLvY7yzkKTRn6GHdW&#xA;HcHKNNqZ4JicDRDbnwRyxMZDYvW3XTPO3lfoEd+hO7QXCj+36VOem6DWx1OITj8R3F4fV6aWHIYH&#xA;8B4veWk9ndTWtwvCeBzHIvgymhzNcZSxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ku&#xA;xV2KuxVNfK2kjVdfs7JhWJ5OU3/GNByf7wKYqz781NZMNtb6PCePrD1pwNvgU0RfkWFfozk/ajWG&#xA;MY4R/Fufd0+37noOwtNcjkPTYfpebRiMyKJCRHUcyoqQtd6Akb5xcavfk9Mbrbm918tW+jwaPbrp&#xA;BDWbDksg3ZmPVn/yvHw6Z6l2djwxwx8H6Pv9/m8HrZ5JZD4n1fj7Eq86eS4NbgNzbAR6nGPgfoJA&#xA;P2H/AIHMDtjseOpjxR2yj7fI/oLl9m9pHAeGW8D9jyGe3ngne3mjaOeNuDxsKMGHamefTxyjIxkK&#xA;kOj2EZiQsHZ6X5F8iizEeqapHW7PxW1s3+6vBmH8/gO3z6dr2J2J4dZco9fQd3mfP7vfy5jtTtTj&#xA;vHjPp6nv/Z97MtShsZrGeO/CGzKH1/U2UKNySe1PHOj1EMcsZGSuCt7dNhlOMwYfV0eDaitil9Ot&#xA;g7SWYciB5BRivaozyrUCAyEYyTC9re+wmZgOPaXVk35aa01lrn1J2/0e/HCnYSruh+ndfpzdezms&#xA;OPPwH6Z/f0/U6vtrTceLiHOP3dVb82dIWDVLfU41ot4hSan+/IqAE/NSPuz0F5BgeKuxV2KuxV2K&#xA;uxV2KuxV2KuxV2KuxV2KpnpOhS6hDLcNPFaWsJCNcTc+JcqWCDgrmpC/5kgZh6rWxw8/t5de4HnR&#xA;/FXk4NNLJy/H2jvQmo2Fzp97NZ3K8ZoW4sB08QR8xvmRjycQtpnDhNIfLGDsVdirsVdirsVZ3+UV&#xA;qH1u7uSK+jb8VPgZHH8FOKpb5/umuPNd6SfhiKxIPAIoB/4auea9u5ePVz8qHyD23ZUOHTx892PZ&#xA;qHYp/wCUvNt3oN33lsJT/pFv+HNK9GH45tuyu1Z6WffjPMfpHn97r9foI6iPdMci9ksb60v7SO7t&#xA;JBLBKKo4/UfAjuM9GwZ4ZYCcDcS8ZlxSxyMZCiENcaBpNxqkOqS26tewCiSH8CR0JXse2U5NBhnl&#xA;GUx9cfx9nRshq8kcZxg+ko2aaKGJ5pnEcUYLO7GgAG5JJzJnMRBJNANEYmRoc3knnXzrLrMps7Mm&#xA;PTIz8jMR+03+T4D6T7ef9s9snUHghtiH+y/Z3B6/s3s0YRxS+v7mJ5oHbqtncva3cFymzwSLIp90&#xA;YMP1ZZhyGExIc4kH5MMkBKJieop6p+aUCT+VPXG/oTRyKfZqp/xvnrgNvnZFPHsKuxV2KuxV2Kux&#xA;V2KuxV2KuxV2KuxV2KplpWuz6fFLB6EN3bSkO0FwGZA4UqGAVk34sf8AbAzE1Ojhm+oA+/cdfMd5&#xA;/FORg1MsfL7Px5IXUL64v7yW7uG5TSmrEdNhQAfICmX4sYgKapz4jaHyxg7FXYq7FXYq7FXof5PO&#xA;BeamncxxEfIM39cVY35vjZPM+pq3Uzu30N8Q/Xnl3a0a1WT+sXu+zzeCHuSjNe5jgCTQbk9Bir1z&#xA;8vPLmpaVYyT3srIbqjLYnon+U3g58Pv9vQPZ/s/LgxmUyRxfw93n7/wfLkO19ZDLMCI+n+L8dGXZ&#xA;0Lp0i856Dd61o7W1rOYpUPMRVoktP2X/AIe+artjQz1OHhgaPOuh8i5/Z2qjhycUhY+54rcW89vO&#xA;8E6GOaMlZI2FCCOxzzXJjlCRjIUQ9tCYkLG4KzIsnYq9f/MM+n5IuEcDk3oJv2IkU7fdnr8BUQ+d&#xA;SNkvGMkxdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVZd+V1+tt5oWFjRbyJ4&#xA;R4chSQf8QpiqI/M/TmtvMf1oD93exq4btzQcGH3AH6c8+9pdPwani6TH2jb9T1/Ymbiw8PWJ/axE&#xA;Ak0G5PQZz7uHp/kXyKLMR6pqkdbs/FbWzf7q8GYfz+A7fPp3HYnYnh1lyj19B3eZ8/u9/Llu1O1O&#xA;O8eM+nqe/wDZ97OJpooYnmmcRxRgs7saAAbkknOnnMRBJNAOijEyNDm87vPzTddcU20XPSI6o4Ip&#xA;JJU/3gr0p+yPv9uPy+05Gf0i8I+Z8/1D5+XR4+wwcXqP7z7B5PQLG+tL+0ju7SQSwSiqOP1HwI7j&#xA;OtwZ4ZYCcDcS8/lxSxyMZCiGPedPJcGtwG5tgI9TjHwP0EgH7D/wOaftjseOpjxR2yj7fI/oLsez&#xA;e0jgPDLeB+x5BcW89vO8E6GOaMlZI2FCCOxzz3JjlCRjIUQ9hCYkLG4KP8t6c2o67ZWgFRJKpk/1&#xA;E+J/+FBzK7O0/jZ4Q7z9g3P2NGszeHilLyZ5+bmoLHpNpYg/HcTeow/yIlpv/snGeqvAvKcVdirs&#xA;VdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVVrO6mtLuG6hNJoHWSM/wCUhqMVeveY&#xA;bGDzd5ThvrEcrhV9e2XvyApJF89qfMDNP232f+Zw+n647j9I+P3ux7M1fg5d/plsf1vJAXjcMpKS&#xA;IagjYgj+OebgkHuIe12Iep+TPP1ve2/1TVpVhvIVJFw5CrKqipJPQMB18c7rsft2OSPBmNTHXv8A&#xA;2vK9o9lGB4sYuJ6d37GL+dfOsusymzsyY9MjPyMxH7Tf5PgPpPto+2e2TqDwQ2xD/Zfs7g7Ts3s0&#xA;YRxS+v7mJ5oHbp/5S823eg3feWwlP+kW/wCHNK9GH45tuyu1Z6WffjPMfpHn97r9foI6iPdMciz/&#xA;AMx/mBpljpkcunSpdXd0nK3UbhAduUg7U/l61zrO0O3sWLEDjIlOQ28vM/qef0fZM5zImOGMef7H&#xA;kt1c3F1cSXFxIZZ5WLSSNuSTnAZMkpyMpG5F66EBECMRQD0j8sPLrW8D6zcrxedeFqp6iOvxP/si&#xA;Nvb552fs12eYxOaXOW0fd3/H8c3mu29ZxHwo9OfvYZ5715dY8wTSxNytbf8AcW5HQqpNW/2TVPyp&#xA;nVvPsexV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ksv8Ay/8AOI0W6Nle&#xA;sf0bcNUt19KTpz/1T+1irI/O3kU3xbWNGAeWQc57dKESV39SMjYk9x3+fXk+2+wzMnLhHq6x7/Me&#xA;fl1970HZfaogBjycuh7vIvNmVlYqwKspoynYgjsc4ogg0XpgbaxS7FXYq7FWZeTPIc+pSJfakjRa&#xA;cPiSM1VpvCncJ79+3jnR9j9hyzEZMorH/uv2fgOl7R7VGIGEN5/d+1OvzE84Q2Fo2h6awFzIvC4Z&#xA;NhDHSnAU6Mw29hnegACg8mTe5eV4UOxV2KuxV2KuxV2KuxV2KuxV2KuxV6v/AMqh0T/ltuf+Sf8A&#xA;zTirv+VQ6J/y23P/ACT/AOacVd/yqHRP+W25/wCSf/NOKu/5VDon/Lbc/wDJP/mnFXf8qh0T/ltu&#xA;f+Sf/NOKu/5VDon/AC23P/JP/mnFXf8AKodE/wCW25/5J/8ANOKu/wCVQ6J/y23P/JP/AJpxV3/K&#xA;odE/5bbn/kn/AM04q7/lUOif8ttz/wAk/wDmnFXf8qh0T/ltuf8Akn/zTirv+VQ6J/y23P8AyT/5&#xA;pxVkvl7QTotr9UjvJrm2H93HNxPD2UqBt7Yqpa95O0PWqvcxenc9rmKiv9PUN9IzWa7sjBqd5Cpd&#xA;45/tc7S9o5cO0Tce4sKv/wAp9UjYmxu4p4+wlDRv8tg4/HOZz+y2UH93ISHnsf0u7xdvYz9cSPdu&#xA;lh/LfzYCR9WQ07iWP+uYR9ndX/NHzDlfyzp+/wCwoyz/ACr16Vh9Zmgtk77mRvoAFP8AhsycPsxq&#xA;JH1GMR8/x82nJ27hH0gn7GXaH+XehaayzTA31yu4eYDgD4rGNvvrnQaL2fwYTcvXLz5fL9dun1Xa&#xA;+XLsPTHy/WyK9t5bi2eGKdrZnHH1owC6j/J5VAP0ZvXVMMf8pNHd2d766Z2JLMShJJ3JJK4q1/yq&#xA;HRP+W25/5J/804q7/lUOif8ALbc/8k/+acVd/wAqh0T/AJbbn/kn/wA04q7/AJVDon/Lbc/8k/8A&#xA;mnFXf8qh0T/ltuf+Sf8AzTirv+VQ6J/y23P/ACT/AOacVd/yqHRP+W25/wCSf/NOKu/5VDon/Lbc&#xA;/wDJP/mnFXf8qh0T/ltuf+Sf/NOKu/5VDon/AC23P/JP/mnFXf8AKodE/wCW25/5J/8ANOKu/wCV&#xA;Q6J/y23P/JP/AJpxVneKuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ku&#xA;xV2KuxV2KuxV2KuxV2KuxV//2Q==</xapGImg:image>
- </rdf:li>
- </rdf:Alt>
- </xap:Thumbnails>
- </rdf:Description>
- <rdf:Description rdf:about=""
- xmlns:xapMM="http://ns.adobe.com/xap/1.0/mm/"
- xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#">
- <xapMM:DocumentID>uuid:CF79BD34E729DD119F1AC516D799FE17</xapMM:DocumentID>
- <xapMM:InstanceID>uuid:b1f6bd12-8b64-4b4f-af46-c9c1b6cb9114</xapMM:InstanceID>
- <xapMM:DerivedFrom rdf:parseType="Resource">
- <stRef:instanceID>uuid:f1c065ce-15b7-453e-bf4a-735a529f4226</stRef:instanceID>
- <stRef:documentID>uuid:65E6390686CF11DBA6E2D887CEACB407</stRef:documentID>
- </xapMM:DerivedFrom>
- </rdf:Description>
- <rdf:Description rdf:about=""
- xmlns:illustrator="http://ns.adobe.com/illustrator/1.0/">
- <illustrator:Type>Document</illustrator:Type>
- <illustrator:StartupProfile>Web</illustrator:StartupProfile>
- </rdf:Description>
- <rdf:Description rdf:about=""
- xmlns:xapTPg="http://ns.adobe.com/xap/1.0/t/pg/"
- xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#"
- xmlns:xapG="http://ns.adobe.com/xap/1.0/g/">
- <xapTPg:NPages>1</xapTPg:NPages>
- <xapTPg:HasVisibleTransparency>False</xapTPg:HasVisibleTransparency>
- <xapTPg:HasVisibleOverprint>False</xapTPg:HasVisibleOverprint>
- <xapTPg:MaxPageSize rdf:parseType="Resource">
- <stDim:w>600.000000</stDim:w>
- <stDim:h>800.000000</stDim:h>
- <stDim:unit>Pixels</stDim:unit>
- </xapTPg:MaxPageSize>
- <xapTPg:PlateNames>
- <rdf:Seq>
- <rdf:li>Cyan</rdf:li>
- <rdf:li>Magenta</rdf:li>
- <rdf:li>Yellow</rdf:li>
- <rdf:li>Black</rdf:li>
- </rdf:Seq>
- </xapTPg:PlateNames>
- <xapTPg:SwatchGroups>
- <rdf:Seq>
- <rdf:li rdf:parseType="Resource">
- <xapG:groupName>Default Swatch Group</xapG:groupName>
- <xapG:groupType>0</xapG:groupType>
- <xapG:Colorants>
- <rdf:Seq>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>White</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>255</xapG:red>
- <xapG:green>255</xapG:green>
- <xapG:blue>255</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>Black</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>0</xapG:green>
- <xapG:blue>0</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>RGB Red</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>255</xapG:red>
- <xapG:green>0</xapG:green>
- <xapG:blue>0</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>RGB Yellow</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>255</xapG:red>
- <xapG:green>255</xapG:green>
- <xapG:blue>0</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>RGB Green</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>255</xapG:green>
- <xapG:blue>0</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>RGB Cyan</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>255</xapG:green>
- <xapG:blue>255</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>RGB Blue</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>0</xapG:green>
- <xapG:blue>255</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>RGB Magenta</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>255</xapG:red>
- <xapG:green>0</xapG:green>
- <xapG:blue>255</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=193 G=39 B=45</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>193</xapG:red>
- <xapG:green>39</xapG:green>
- <xapG:blue>45</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=237 G=28 B=36</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>237</xapG:red>
- <xapG:green>28</xapG:green>
- <xapG:blue>36</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=241 G=90 B=36</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>241</xapG:red>
- <xapG:green>90</xapG:green>
- <xapG:blue>36</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=247 G=147 B=30</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>247</xapG:red>
- <xapG:green>147</xapG:green>
- <xapG:blue>30</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=251 G=176 B=59</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>251</xapG:red>
- <xapG:green>176</xapG:green>
- <xapG:blue>59</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=252 G=238 B=33</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>252</xapG:red>
- <xapG:green>238</xapG:green>
- <xapG:blue>33</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=217 G=224 B=33</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>217</xapG:red>
- <xapG:green>224</xapG:green>
- <xapG:blue>33</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=140 G=198 B=63</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>140</xapG:red>
- <xapG:green>198</xapG:green>
- <xapG:blue>63</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=57 G=181 B=74</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>57</xapG:red>
- <xapG:green>181</xapG:green>
- <xapG:blue>74</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=0 G=146 B=69</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>146</xapG:green>
- <xapG:blue>69</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=0 G=104 B=55</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>104</xapG:green>
- <xapG:blue>55</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=34 G=181 B=115</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>34</xapG:red>
- <xapG:green>181</xapG:green>
- <xapG:blue>115</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=0 G=169 B=157</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>169</xapG:green>
- <xapG:blue>157</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=41 G=171 B=226</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>41</xapG:red>
- <xapG:green>171</xapG:green>
- <xapG:blue>226</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=0 G=113 B=188</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>113</xapG:green>
- <xapG:blue>188</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=46 G=49 B=146</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>46</xapG:red>
- <xapG:green>49</xapG:green>
- <xapG:blue>146</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=27 G=20 B=100</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>27</xapG:red>
- <xapG:green>20</xapG:green>
- <xapG:blue>100</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=102 G=45 B=145</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>102</xapG:red>
- <xapG:green>45</xapG:green>
- <xapG:blue>145</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=147 G=39 B=143</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>147</xapG:red>
- <xapG:green>39</xapG:green>
- <xapG:blue>143</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=158 G=0 B=93</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>158</xapG:red>
- <xapG:green>0</xapG:green>
- <xapG:blue>93</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=212 G=20 B=90</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>212</xapG:red>
- <xapG:green>20</xapG:green>
- <xapG:blue>90</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=237 G=30 B=121</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>237</xapG:red>
- <xapG:green>30</xapG:green>
- <xapG:blue>121</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=199 G=178 B=153</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>199</xapG:red>
- <xapG:green>178</xapG:green>
- <xapG:blue>153</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=153 G=134 B=117</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>153</xapG:red>
- <xapG:green>134</xapG:green>
- <xapG:blue>117</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=115 G=99 B=87</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>115</xapG:red>
- <xapG:green>99</xapG:green>
- <xapG:blue>87</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=83 G=71 B=65</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>83</xapG:red>
- <xapG:green>71</xapG:green>
- <xapG:blue>65</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=198 G=156 B=109</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>198</xapG:red>
- <xapG:green>156</xapG:green>
- <xapG:blue>109</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=166 G=124 B=82</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>166</xapG:red>
- <xapG:green>124</xapG:green>
- <xapG:blue>82</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=140 G=98 B=57</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>140</xapG:red>
- <xapG:green>98</xapG:green>
- <xapG:blue>57</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=117 G=76 B=36</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>117</xapG:red>
- <xapG:green>76</xapG:green>
- <xapG:blue>36</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=96 G=56 B=19</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>96</xapG:red>
- <xapG:green>56</xapG:green>
- <xapG:blue>19</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=66 G=33 B=11</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>66</xapG:red>
- <xapG:green>33</xapG:green>
- <xapG:blue>11</xapG:blue>
- </rdf:li>
- </rdf:Seq>
- </xapG:Colorants>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:groupName>Web Color Group</xapG:groupName>
- <xapG:groupType>1</xapG:groupType>
- <xapG:Colorants>
- <rdf:Seq>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=236 G=28 B=36</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>236</xapG:red>
- <xapG:green>28</xapG:green>
- <xapG:blue>36</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=0 G=169 B=157</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>169</xapG:green>
- <xapG:blue>157</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=102 G=45 B=145</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>102</xapG:red>
- <xapG:green>45</xapG:green>
- <xapG:blue>145</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=139 G=146 B=152 1</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>139</xapG:red>
- <xapG:green>146</xapG:green>
- <xapG:blue>152</xapG:blue>
- </rdf:li>
- </rdf:Seq>
- </xapG:Colorants>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:groupName>Grayscale</xapG:groupName>
- <xapG:groupType>1</xapG:groupType>
- <xapG:Colorants>
- <rdf:Seq>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=100</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>255</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=90</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>229</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=80</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>204</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=70</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>178</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=60</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>153</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=50</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>127</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=40</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>101</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=30</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>76</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=20</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>50</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=10</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>25</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=5</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>12</xapG:gray>
- </rdf:li>
- </rdf:Seq>
- </xapG:Colorants>
- </rdf:li>
- </rdf:Seq>
- </xapTPg:SwatchGroups>
- </rdf:Description>
- <rdf:Description rdf:about=""
- xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
- <pdf:Producer>Adobe PDF library 8.00</pdf:Producer>
- </rdf:Description>
- </rdf:RDF>
-</x:xmpmeta>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<?xpacket end="w"?> endstream endobj 2 0 obj <</Count 1/Type/Pages/Kids[5 0 R]>> endobj 14 0 obj <</Intent 15 0 R/Usage 16 0 R/Name(Layer 1)/Type/OCG>> endobj 20 0 obj <</Intent 21 0 R/Usage 22 0 R/Name(Layer 2)/Type/OCG>> endobj 38 0 obj <</Intent 39 0 R/Usage 40 0 R/Name(Layer 2)/Type/OCG>> endobj 56 0 obj <</Intent 57 0 R/Usage 58 0 R/Name(Layer 2)/Type/OCG>> endobj 76 0 obj <</Intent 77 0 R/Usage 78 0 R/Name(Layer 2)/Type/OCG>> endobj 94 0 obj <</Intent 95 0 R/Usage 96 0 R/Name(Layer 2)/Type/OCG>> endobj 95 0 obj [/View/Design] endobj 96 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 77 0 obj [/View/Design] endobj 78 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 57 0 obj [/View/Design] endobj 58 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 39 0 obj [/View/Design] endobj 40 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 21 0 obj [/View/Design] endobj 22 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 15 0 obj [/View/Design] endobj 16 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 93 0 obj [94 0 R] endobj 5 0 obj <</CropBox[-99.5 99.5 700.5 699.5]/Parent 2 0 R/Contents 98 0 R/BleedBox[0.0 0.0 600.0 800.0]/PieceInfo<</Illustrator 86 0 R>>/ArtBox[-99.5 99.5 700.5 699.5]/MediaBox[0.0 0.0 600.0 800.0]/Thumb 102 0 R/TrimBox[0.0 0.0 600.0 800.0]/Resources<</Properties<</MC0 94 0 R>>/ExtGState<</GS0 97 0 R>>>>/Type/Page/LastModified(D:20080530235524-07'00')>> endobj 98 0 obj <</Length 1028/Filter/FlateDecode>>stream
-H‰ÜWËn7 ÝÏWè®LR¢Û8EWAtÑšdáHòÿ@õš¹öÄqP´À FâC$sïÞÞ»»7÷ä^½¾wyMÕŸ_>nw¿ÿAîã×SñÅ%"§%ù Å}ùkû°}±àÐ{ÁéŸîŸýAÇg,„?v’²O5—”<%qïÿÞŒbÏ ƒ–Öèƒw ²þßo—XA')îÜx'£cGƒuÈvñ¡š|Ô?lïày„MÇç#«Õ§£¡¸Ôxmt?–€x¨»8DÆ×ÞìO^jØ9FƸŒmse¼Ê|¤yW<®4Ävç ¢ÉWªpC½†
-Íì gW|fP.ŸK´[«Ód‰é Re
-N's0–£vAI* £Œa›‘²p?š³øRRž%©Ok2þTMÆÿ¥&9“/9Ïš<Á’ÿuUòY–äY gò¹wZNÈëZž+Ï“ŽÊY{>“>í¦7X£–޵j/RŽÌ·U¤'¨†ÖtUÕ×XΪ•cnÃÔÊ5ÔtV®§£´7gšà%¥< ©€>Gûl"Ô<ž¡ö‰›ø9Ÿ‚/8šà‹ä‚_´OçXø–¦s¨b•Ñ*äÚŸÐ'³ùsË“9¶ÉsþîdÎm2ÇD?žÌJqH¸zNñÐ
-5úXm\õµ- rAžYþÚ×ì%µÈè¢ì³†Á˜ê8ÁGýb>Jub^zwù¡oòâB9`ŒÑ Rš|É 3©PC°ö¼N…X¼ˆ©ÈpAø–×Ö'-mInìXô,r—}
- 3#VK„Ž‚6±äà‚öR7ÅýÅ<6b “}pWm—FË©%eEÞd¦f»2ëºqz–#Oñ!GÙ2+á—•A¶<…RéÍ={ îÁ‚«ÍãŠâÉND¡
-8;Z,gc#LWD&;:X<0iX643;>lBC4Zq;8hR9e/SmKLZ%s-N5OUZ,"@eRq)74cR*Y<j$
-XC-TOdI&rmVj8PLMJK;eN0tZm]$G+3*fGNS(9KX=&Y%r<M^+]kF]B6#oeQ^h6,s]X
-jL?]$dVLp[=qm]W'Pcj?!hZ5X2QJh2,*qkVV=2]YIuZn!NcK)24bq4AI^ZbT+NuO$
-Gj&j\\Bb05cD7R?\<^CJp"Lj&F5Y-7/m>:`No%b@,39>0PX1p[nbV;3`6MTMfJb-A
-(;F(Q9,Q9lHnXe@Th((dk[B)bSg%pUr!<,RcTK"W1O4ip4,TFHX2+h&mSR&N@]+t!
-]%Ua/Oq6c%0lqM3S0+i\dK@_<HjT.E/No$npQub;=@WC21Ui4/TD"$HO^W%Sci\@Y
-'kqZT)gL&H(bL7(H>mf8%1WX&ddT!Fqpd%g9Dp#7l5Y<Qs2U$WjQ\fejOAGK])!Lp
-I%ERVr<2cVp1/5tk)W?aqpohIYPn?Ne.X]b*#lcN!RRb.cI)en'K,4&i^cCHjnOBf
-a3_C^UHfG(Ifp+V!"_"A5(%pT8#--jZM#+8"S@LZCsAqD@bBcZ;'Ynq4D+I8WY%<T
-p(WT=o!BJ8RYj7+MYNdF8$YV81VN3tfZhH:7>Nm_.EG^Ti"%cD-3rA#;@7fD-DSlF
-kPY>ClZ"%-^6@#uJt273oc,!%cnU`53=""TFQSE&qp%'ra,iOR=jP#0i"%e^5o`,L
-O61N=UOYCS57>$b#C7Pi.,mE\Y6$0d5C8>TjSZ5M&8I*n7'Ge;.K\;JWjnHfgog]#
-^KVH0i9?s$,XBlk\0mm*XrqL[i>B/rSrk-as*ch*o%S&Wr!i_R(:8\~> endstream endobj 97 0 obj <</OPM 1/BM/Normal/CA 1.0/OP false/SMask/None/ca 1.0/AIS false/op false/Type/ExtGState/SA true>> endobj 100 0 obj [/Indexed/DeviceRGB 255 101 0 R] endobj 101 0 obj <</Length 428/Filter[/ASCII85Decode/FlateDecode]>>stream
-8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0
-b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup`
-E1r!/,*0[*9.aFIR2&b-C#s<Xl5FH@[<=!#6V)uDBXnIr.F>oRZ7Dl%MLY\.?d>Mn
-6%Q2oYfNRF$$+ON<+]RUJmC0I<jlL.oXisZ;SYU[/7#<&37rclQKqeJe#,UF7Rgb1
-VNWFKf>nDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j<etJICj7e7nPMb=O6S7UOH<
-PO7r\I.Hu&e0d&E<.')fERr/l+*W,)q^D*ai5<uuLX.7g/>$XKrcYp0n+Xl_nU*O(
-l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 86 0 obj <</Private 87 0 R/LastModified(D:20080530235524-07'00')>> endobj 87 0 obj <</ContainerVersion 11/RoundtripVersion 13/CreatorVersion 13/AIMetaData 88 0 R/AIPrivateData1 89 0 R/AIPrivateData2 90 0 R/AIPrivateData3 91 0 R/NumBlock 3/RoundtripStreamType 1>> endobj 88 0 obj <</Length 914>>stream
-%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 13.0 %%AI8_CreatorVersion: 13.0.0 %%For: (Jason von Nieda) () %%Title: (Android Buttons.ai) %%CreationDate: 5/30/08 11:55 PM %%BoundingBox: -36 -36 951 636 %%HiResBoundingBox: -36 -36 950.5 636 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 9.0 %AI12_BuildNumber: 406 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Registration]) %AI3_Cropmarks: 0 0 800 600 %AI3_TemplateBox: 400 300 400 300 %AI3_TileBox: 22 12 756 588 %AI3_DocumentPreview: None %AI5_ArtSize: 600 800 %AI5_RulerUnits: 6 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI9_OpenToView: -501.5 774.5 1 1619 1056 18 0 0 73 75 0 0 1 1 1 0 1 %AI5_OpenViewLayers: 7 %%PageOrigin:-102.3003 -302.2988 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %AI9_Flatten: 1 %AI12_CMSettings: 00.MO %%EndComments endstream endobj 89 0 obj <</Length 15260>>stream
-%%BoundingBox: 73 -19 951 595 %%HiResBoundingBox: 73 -18.4619 950.5 595 %AI7_Thumbnail: 128 92 8 %%BeginData: 15124 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FD807D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52FD077D %527D7D7D52FD047DA8FD067D527D7D7D527D7D7D527D7D7D527D7D7D527D %7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D %527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D %7D7D52FD197DA87D7D7DA8FD097DA87D7D7DA8FD577D527D527D527D527D %527D527D527D527D527D527D7D7DFD0552A87D7D527D527D7D7DFD05527D %7D7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D %527D527D527D527D527D527D527D527D527D527D527D527D527D527D527D %527D527D527D527D527D527D527D527D527D527D527D527D52FD157DA852 %7D527D527D52A8FD057DA8527D527D525252A8FD577D527D7D7D527D7D7D %527D7D7D527D7D7D52A87D534C5352534C537D7D527D52A852FD0B7D527D %7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D %527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D %7D7D527D7D7D527D7D7D527D7D7D527D7D7D52FD167D29240324242429FD %077DA8FD05FFFD577D527D527D527D527D527D527D527D527D527D527D52 %53294D294D29537C7D527D52A8527D7DA87DA8FD047D527D527D527D527D %527D527D527D527D527D527D527D527D527D527D527D527D527D527D527D %527D527D527D527D527D527D527D527D527D527D527D527D527D527D527D %527D527D527D527D527D527D527D52FD157DA8527D527D587D52A8FD067D %527D527D527D52A8FD557D527D7D7D527D7D7D527D7D7D527D7D7D52FD05 %7D5252527D52FD057D527D7D7D527D5252527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D52FD1C7D52A8FD0A7D527D7DA8FD577D527D52 %7D527D527D527D527D527D527D527D527D52FD077D527D527D527D52FD07 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D52FD837D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D52FD817D527D527D527D527D7DA87D7D7DA87D7D527D527D527D7D %A87DA77D7D527D527D527D527D7DA8FD047D527D527D527D527D527D527D %527D527D527D527D527D527D527D527D527D527D527D527D527D527D527D %527D527D527D527D527D527D527D527D527D527D527D527D527D527D527D %527D527D527D527D527D527D52FD097DA8FD057DA8FD067DA87D5277527D %7DA8FD087D5276527DA8FD567D527D7D7D527D7DA852527DFF7D5252A852 %FD057D525302535252FD047D527D7D7D52766876527D7D7D527D7D7D527D %7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D %527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D %7D7D527D7D7D527D7D7D527D7D7D52FD097DA87D52527DFF7D52FD067DA8 %527D5224297D52FD067DA8527D7693767D52A8FD557D527D527D52FD047D %FFA8FFA8FFFD047D527D7D53232A0224232952A7527D527D526F68936893 %6875597D527D527D527D527D527D527D527D527D527D527D527D527D527D %527D527D527D527D527D527D527D527D527D527D527D527D527D527D527D %527D527D527D527D527D527D527D527D527D527D527D527D527D52FD077D %A87DA8A8FFFFFFA8A87DA87D7D7DA84C2A2924234E29FD077D6F9368936F %936FFD587D52FD057D52527DFF7D52527D7D7D527D7D52527D034D527C52 %7D52FD047D52527668765252FD047D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7D52FD0A7D527DFF7D52FD067DA87D7C52244D7C52A8FD057DA8 %527D768C527D7DA8FD557D527D527D527D527D7D7D527D527D7D7D527D52 %7D52A87D522853527D7D7D527D527D7DA852764B5252A87D7D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D52FD0B7DA87DA8FD097DA87DA7 %7DA8FD097DA87D847DA8FD577D527D7D7D527D7D7D52FD077D527D7D7D52 %7D52FD057D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D52FD0D7DA27D7EFD737D527D527D527D527D7D %A781815D837D7D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D52FD09 %7DA75C5C82815688FD737D527D7D7D53A75C5C56FF825C32827D7D527D7D %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D52FD077D7E825C5C81FFAD5C5C5CA8 %FD6F7D527D527D527D7D5D82FFCFFFA8FFA75C7D7D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D52FD077DA2818183ADFFCF82825CA8FD6F7D527D7D %7D527D7D83325C56FF825C3281FD047D527D7D7D527D7D7D527D7D7D527D %7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D %527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D %7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D %52FD0B7D81325DAE82328083FD707D527D527D527D527D7D82565C56817C %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D52FD0B7DA782A77D7E %FD737D527D7D7D527D7D7D537D7D7D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D52FD817D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D52FD817D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52FD837D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D52FD837D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7D527D7D7D527D7D7D52FD817D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D52FD817D527D7D %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52FD047DA8FD06 %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52FD3B %7DA8A8FD09FFA8A8FD3B7D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527DA8FD0FFFA87D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D52FD357DA8FD06FFC9C9C8FD04C9FD06FFA8FD397D527D7D7D %527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D %7D7D527D7D7D527D7D7D52FD047DFD05FFC8C198C098C098C098C098C2C9 %FD05FFFD047D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D %527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52FD327DA8FF %FFFFCFC898C0BAC098C0C0C098C0C0C098C0C0C9CFFFFFFFA8FD347D527D %527D527D527D527D527D527D527D527D527D527D527D527D527D527D527D %527D527D527D527D527D527D527D527D7DFFFFFFA0C098C098C098C098C0 %98C098C098C098C098C1A7FFFFFFA87D527D527D527D527D527D527D527D %527D527D527D527D527D527D527D527D527D527D527D527D527D527D527D %527D527D52FD307DA8FFFFFFC1FD13C098C0C8FFFFFFA8FD327D527D7D7D %527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D %7D7D527D7D7D527D7D7D527D7DFFFFFF9FBA98C098C098C098C098C098C0 %98C098C098C098C098C0C1FFFFFF7D7D527D7D7D527D7D7D527D7D7D527D %7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D %52FD317DFFFFFFC1C0C0C098C0BAC098C0C0C098C0C0C098C0C0C098C0C0 %C098C0C2FFFFFFFD317D527D527D527D527D527D527D527D527D527D527D %527D527D527D527D527D527D527D527D527D527D527D527D52A8FFFFA0BA %98C098C098C198C098C098C098C098C098C098C098C098C098C0C8FFFFFF %527D527D527D527D527D527D527D527D527D527D527D527D527D527D527D %527D527D527D527D527D527D527D527D52FD2D7DA8FFFFC9C0BAC0C0C098 %C9FFC198FD09C0BAC9CFC1BAFD05C0CAFFFFA852FD307D527D7D7D527D7D %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527DA8FFCFC198C098C098C9FFFFFFC198C098C098C098C098C9FF %FFCAC198C098C098C1FFFFA87D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52FD2D %7DFFFFC998C0C0C098C9FD05FFC198C0C0C098C0BAC9FD04FFCAC1C0C098 %C0BACFFFFFA8FD2E7D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D527D52A8FFFF9EC098C098 %C1FD06FFCAC198C098C098C8FD06FFA7C098C098C09FFFFFFF527D527D52 %7D527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D52FD2C7DFFFFC9C0BAC0C0C0BAC9FD06FFCFC1BAC0 %98C9FD07FFC7FD06C0CAFFFFFD2E7D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7DFFFF %C898C098C098C098C9FD06FFCAC198C8FD06FFCFC198C098C098C098C9FF %FF7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7D527D7D7D527D7D7D52FD2C7D52A8FFFF9EC0C0C098C0C0C098 %C9FD06FFCAC9FD07FFC1BAC098C0C0C098C0C1FFFFA8FD2D7D527D527D52 %7D527D537D7CA7767D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527DA8FFCAC098C098C098C098C098C9FD0CFFCFC198C098C0 %98C098C098C1FFFFA87D527D527D527D527D527D527D527D527D527D527D %527D527D527D527D527D527D527D527D527D527D527D52FD0A7D7CCEC9C9 %FD1D7DFFFFCFBAFD0AC0CFFD0BFFC798FD0AC0FFFFFFFD2F7D527D7D7D52 %7D53A7C8C1C97D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7DA8FFC9C098C098C098C098C098C098C9FD08FFCFC198C098C0 %98C098C098C098C0CAFFA87D7D7D527D7D7D527D7D7D527D7D7D527D7D7D %527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52FD0B7DC9C9 %C9FD1D7DFFFFC9BAC098C0C0C098C0C0C098C0BACFFD07FFC898C0C0C098 %C0C0C098C0C0C098FFFFFFFD2D7D527D527D527D527D527D7CA1527D527D %527D527D527D527D527D527D527D527D527D527D527D527D527DA8FFA7C0 %98C098C098C098C098C098C2CFFD07FFC9C098C098C098C098C098C098C0 %A8FFA87D527D527D527D527D527D527D527D527D527D527D527D527D527D %527D527D527D527D527D527D527D527D52FD2B7DFFFFCFFD0AC098C8FD0A %FFCAC1BAFD0AC0FFFFFFFD2D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527DA8FFCAC098 %C098C098C098C098C1FD0CFFCAC098C098C098C098C098C0CFFFA87D527D %7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D %527D7D7D527D7D7D52FD2C7D52A8FFFF9EC0C0C098C0C0C098C8FD07FFCF %FD06FFCAC1BAC098C0C0C098C0C1FFFFFFFD2D7D527D527D527D527D527D %527D527D527D527D527D527D527D527D527D527D527D527D527D527D527D %527D7DFFFFC298C098C098C098C1FD07FFC298CFFD06FFA7C098C098C098 %C098C8FFFF7D7D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527D527D52FD2B7DA8FFFFC9FD05C0 %BAC7FD07FFC898C0C0CFFD06FFCAC0BAC0C0C0BAC0CAFFFFA8FD2F7D527D %7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D %527D7D7D527D7D7D52FFFFFF98C098C098C1FD07FFC898C098C098CFFD06 %FFC9C098C098C09EFFFFFF527D7D7D527D7D7D527D7D7D527D7D7D527D7D %7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52FD2D7DFF %FFC898C0C0C09ECFFD05FFC898C0C0C098C0C0CFFD05FFC8BAC098C0BAC9 %FFFFA8FD2E7D527D527D527D527D527D527D527D527D527D527D527D527D %527D527D527D527D527D527D527D527D527D527DA8FFCAC098C098C098CF %FFFFFFC898C098C098C098C098CFFFFFFFC298C098C098C1CFFFA87D527D %527D527D527D527D527D527D527D527D527D527D527D527D527D527D527D %527D527D527D527D527D527D52FD2C7D52A8FFFFC8FD06C0CFFFC9BAFD0A %C0FFFFC898C0C0C0BAC0C9FFFFFFFD2F7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52FD04 %7DFFFFFF9EC098C098C09EC898C098C098C098C098C098C09EC898C098C0 %98C09FFFFFFFFD047D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52 %7D7D7D527D7D7D527D7D7D527D7D7D527D7D7D52FD317DFFFFFF9EC0C0C0 %98C0BAC098C0C0C098C0C0C098C0C0C098C0C0C098C0C1FFFFFFA8FD307D %527D527D527D527D527D527D527D527D527D527D527D527D527D527D527D %527D527D527D527D527D527D527D527DA8FFFFCA98C098C098C098C098C0 %98C098C098C098C098C098C098BA98FFFFFFA87D527D527D527D527D527D %527D527D527D527D527D527D527D527D527D527D527D527D527D527D527D %527D527D527D52FD307DA8FFFFCFC0C0BAFD13C0C1FFFFFFA8FD347D527D %7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D %527D7D7D527D7D7D527D7D7D527DA8FFFFFF9FC098C098C098C098C098C0 %98C098C098C098C0C2FFFFFFA87D527D7D7D527D7D7D527D7D7D527D7D7D %527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D %7D7D52FD047D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D %527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527DA8FFFFFFC9C198C0 %C0C098C0C0C098C0C0C098C0BAC1C9FFFFFFA87D527D527D7D7D527D7D7D %527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D7D7D527D %7D7D527D7D7D527D7D7D527DA8A8A87DA8A8A87DA8A8A87DA8A8A87DA8A8 %A87DA8A8A87DA8A8A87DA8A8A87DA8A8A87DA8A8A87DA8A8A87DA8A8A87D %A8A8FFFFFFCFC99FC098BA98C098C098C098C09FC9FD04FFA8A87DA8A8A8 %7DA8A8A87DA8A8A87DA8A8A87DA8A8A87DA8A8A87DA8A8A87DA8A8A87DA8 %A8A87DA8A8A87DA8A8A87DA8A8A87DA8A8A8FD39FFCFC9C8C8C1C7C1C8C8 %CFCFFDFCFFFDBFFFFF %%EndData endstream endobj 90 0 obj <</Length 65536>>stream
-%AI12_CompressedDataxœì½ëŽ$¹‘&ú|‡<?~t¬ÓtÒ…ƒâ:g-©!ivµ,5ê’T;uiTWVçéíJ#Ý#2²²4+édUeéAçÅHš}vá?ü_ßüú«ýwþíõWÓnxpÿðǯ_}úðñgH}øç·oüáÓG ýäW?}ðå©òÐþŸó·üà{ýñ‡7Þÿ …¿¼À·ò__ýðáýÔ?¿xóú»W?}øÉOËï~óæÓÛ×å·û÷ß}üðæ»‡ÃŸ>}xÿÃîÕ›ŸÊ»Ke§WŸÊCñ¿LÃòƒ÷?‹ñᛟ—~|ÿÝ›÷8|øß?{øjšñÏýÃ<Íå×ÿÏ›_½þáÊ3Ã.òS§¿ûñÝë÷Ÿ¾ùøáw¯øáøáí‡?üìáøçWï~þêå7¯þÇë·o?üéáðöÕïþÝ•îÆo/oÞ¾.={÷êÓÃÝÜÿ³¿=üøæíw¿øñÝ¿½.]à äé[¬ñ_~(U•Zá3Ó·ÿü®P~ýúÓ§Ò¸ò>ª_ýÓÁ¶¢±üä_õúopØËhüÏŸrµ?|ÿîÕÇÿËÃð0ýî7¯ß}ÿ¶Œv:”ßLåÿËO”öãoÇñÁ)Î1gú]‘×ÿñæõŸ~öð‹ï_S·÷?ýúÍÿ[:R^¯$ê¯~|ûú㿼ó©´;½P§þá»×o +èw/o_ýáé–¯Ó¿yõñ¯?•9ûðöÇOÈDú†2¨_¿úók˜O/øå÷¯ßÿæÃÃö}_æ3¥Pþö~ö˃J—|Æw¤©tßæñÜ$¨ªºS™„oÊ´üòã›?¼yÿ³¯ü0îÊM…iʧq¡JßþÓÇ7ßÕ©KãC¦¿°3»lþ,ò‡Z]àÓ§×ï¹…eŽ?7,0ì~þËÒ‚óûïŽÞÁ ü
-
-7žÊŒ]Ê"ó…O§Â¯±ðm.<¼/¼|,<}>^Jë}Y­Saúè
-÷§²
-–²…çOe}\JýyÄn¼ãÚ[’yÏÆ›èENßÔ¼ Ø’Þwï»ÒÕ^™·gûeßvnÖàpûÇ›‚É
-.N,¨ôyÀ²ÚžÏÿvÔ:ÆÍñ°5RÌSÇâÖ8ÈhgÆaî$ž:$ùuÎÂ/kñͶ!)nV1ˆd s”õ(ˆ(—qÓ*ÃàxÎ\P9Çþœµœ¸±àÉxÙc)ÂÆ%cI¥ÌXb)¡”r8½‘@ä·rät”G<Êé0yDŽs<Ð]Yòr¢W¹ªéÇGŽt:Ð\ⶤ+’<î‹õh,:©à`@êx™LÆã¾QÍÉ lŒ‰H›—MY튴æxX©óž±¸ÆWy£ óFŽÊ!Ï+óõ‚«‘¾™G¬ìºg$?æ@©‹`¸Œ¼m–ÑÚè—AyìcA›ö!ûk"6}ä©XF4•ñ]Êx—Ž¿ËEdþ»7ê«r,IJ"'©¤„›Ø%S`I®•Ç«˜£bì¾c“ʹ"YYŒßpCî(³ÎÈ)%×ùGÄÛr×…6Xr=J
-$+ýzÖ/Í—è+*`¨ˆ±’”7åäuÃn
-qX
-OÅRæ¥L þÀeK9íA6(œppüø=ŽÊ¾ô{_º¶€£•v"U^‚xü° ÈPÔóªèPPÐÁƒÏ£º^J«TTua2Šä|eޝâŸN'»¥[à¶JûI1郙ï:ãŠvÚißЛ™ïç½Î< ÔeÔiúEh™@Ù âƒ3ópBåƒÅ1+ôÌ0!3XVf8^ðÌ Ay!;f…ƒ²ÂYYÁ3+#”ŽlqÁçͬèwcg08€[ÍêqŽß^É=Ž`-»n^óÚ¯h™×~EÚ^Üj^ëâîgv3Û®ñÕ*w¼ÐëR§ùõ<¿Á,öºÜÍ£|éëŠwfÑ×%Oó|jæ¹éºèŸ
-…{–Â0—Â&¡0ƾ0Ä¥0@,3~(Ò÷Pæs.+õXvä±(®©lÙGQ^Ϩ¢P-ͨŒF(FcZX›u®uܦUç1c £Ž»fÕÙ6êö†³m.]…ÿDz†²óËú8–u²Ï‹+Ë&•ËH‘ºŒØPTðsYlDzèöesY‰sY‘¡¬Í±¬Ñ¡¬×sécï}Y˹¬é¹¬îPÖù8{W´­KYþ§² ÊŠYÊÎÊË^'ÁXæo(Zä¹Ìå±Ìè¾Ìk.³;_³¸Î@0*Ð^¡ý•€!}„òÿÎìŒuîËÎkÎîËÎë<¸óúäY…IuÏ™U@5_föïxf+ R4!Ph‡ÁêªL)z—§ÿéoõÿOÑɾùñã÷o_?üª^½µž"W~Qtä©ÓÎc
-¥Ø€–Ηáb<K|‹ãÏFuÛûTëOuÃh¬?ŽÄz#
-) 3®lXÛ´ºa}ƒ‚À+\ÕTXçBÀj‡õ+~! TÖª¬ ´žQŸðèÐ&jkD¥ÔV#P•UÖ™ÔUPXŒ`(b D "Åê)(¦¤“fÖFa,A]áP;A`@¥ BHÓ”ÑrX爘Ω+¨ƒSW&îŠèà{ƒ¯4èŠÃÞ@¤3Õ¼+ª±+ÐжM9£¦ HÊŒ\º°R}qÐÔ¡+Œä ÝPÿ7pò
-îV®~4ѹG£{j>KÌîYŽp –F°:ûŸæsW:ß‹ögÔx3 î)eZýjhS_Üšdv¯ëûص ûK¡¤-°¹t8¡ -ªyf¤G5ØrˆXôC€Í½±] ªÉvë"±DÓ@XàB7Èf]-ÖAaŒ½Å*ÉÖKÀÔž!ÉAŽ8vèÐYøÐ)Ǭc>väà¡£‡âû!ÂÿÄ—‡GP=„袃脎
-ä8X™¿W#øløß‘ÒW8
-åãÀã#GŒC¥ðG´¬kI ™9 rÑÝRÄ™#ïô_T­îìâÎu¾²¿/Œ¦uØ8€A5`J“^‡KËQÈUÈW#JÎ17˜¹C
-h#° 7Ýx#ð »c8ÄpÎ8ùG´íñìÊxŽÍ çt\¦ÓŽ’D°#È.-Å…ò<QÚ8û’§ìK
-‹ˆÄn%tQ E£Ì¬/ЄßÒ?ËÆ¶1íN]9Z4WLÎxß (ç\ÎNý-¿›õä J7ºMw!™~Âë±CÌ®a
-;V¿Ge
-e J/†‚ßC=ùçoµÂ{NÙÞÓÝä<ÚúUïìÞ:jr¡ãuz$Ïßm„½ƒ×O[i^ú•-«Ú¬énEÓzæÕL+Ö1¬aò¾D]¶m»rL(}©PºëÖª¬ÓºFÅ›7ç²8eaF £+~pºq-šÍx0Kp¯žqÍÒ“ì&§ÒñTr,ç﹌߾ŒÜ\F t7_Æ FŒÆ+”±ÊHË¥²kÐðÐùÛ\0—±);Û‰Çeƽ ÔP‘Œ› X´mÑ–5›sÊÇ‹kL
-vƒj
-Õ¨ ÃЛøHr<™Íb` ÍȳÛJ=“Žlp°ûPÒäƒerj•5: –(g‘ÂU’Êf%éÜ(§Ç‹»ç¡U¹ñãnýò®Ÿgt=á¹Å©šÿ…4úšówË›íðO6PËݶ^~Å—MÜ™NÆŸ­óhsŠýœ?Ûô¨?›x³­˜œz²MìÉ6³CKug97hP`<ˆÜ”Ä
-¡v‡Z»˜"ª1b_‘!4H 6Äè%û¼5èw {ëGæ®ûÞbn®q%¤¿oè­#¡ñ"t:ôvðÍàûfð“¾5©È©%hróÚðKêÍ¥“äH¿O•nÃé6L[«bÒK…_¬Â
-ŠAìܸ“ÞZû“zu5+¿(¼ðcçhxl {Çá­5ÏØ§3N£´Ú]ï c6(6ìÄ0{N•¥•~$ÿA‡Êgu&ŸÁƒø
-6`ûÌ1bn¯F^Ù[£Ãµ]7WÞZÙÚ»±¹6Ð;YO(N\zñÎäÙž€øŒÑAÓû2oÀxJ¨W!y„å]“š/7½¤èë¥#)Ts‘'¶Y-S-„ÐÚ€lãßܤå­qÌdí±Öé¬Fgà̃³^Ïl îSôÖ”ó ˆÕí·ê]þ8åaA÷ã7{-l»ÆH.(â’-2·ãðH ¤s-q áåfäqDùGäó€šÆŒØ@fÚ±ú|qÈéç^?àÉS9 Ö:yÌfäu`EЄ(xpd¼?R ÕÂ?œ.g´@@Ba„mD$ðÅ`ÿˆ–%(d[ÚSÂRb1TCÀŒ*ß‘†GŒ6#pQ
-«K!C—Î`—=pÝG ¶èe ^ *ÀуküÒØl!˜ÄVÓu¦ ˜ûŠyǬ0¦[!™‹"™=´½…e*’)0·[y§Ï¹ïa›³>‹·ŽƒÛ0…tܵr)·æ95ˆTd¼úªV«þªÕ,ÒFV¦‘Þ8²Åe‚½­ƒj‰ÏؽBqXkL%+¯¼&Üv°Üæ˜ÝªÕÄ`曷湆ëHš¨ŒWY¯2¡èÄ}v<X 
-":¬[–ì¼Ú0>t·H #¥PEÒdWõé)êq|LJíçבœ’¹Žtoàn¼¾ªI€=eÕÅdºË´ ÿÔØÍçTB©k%•ì‚IeñV Aª¥å@Iœëw7HÒá²®ãÌI‡çq7¶29l¿X•ÔBÉÌ‹,ð_ÎÎË1©IjOô¾ñaZvÀwSØåÉÛ¦=¿.ò·~Ú܇y½ŸËÜïæÆÏ桾SéÏn¨©µaææ_râèÒ±´+ýƒ„Ü~±#ôj{ŠÏù¿¼ÿêÝëïþ`7ˆ/ç/ç/ç/ç/ç/ç/ç/ç/ç/ç/ç/翾xœ¿xœ¿xœ¿xœ¿xœ¿xœ¿xœÿUTøâqþâqþâqþâqþâqþâqþâqþâqþâqþRá_¶Âóóóóóóóóóóóóóóó/äqî§MŸóB¶÷OCêØ3Õýñh—Âfs*{ '¸Ëff—Jñ㟥ÅsðÄ~é¾WqÙt›Ždb’Û}ÇÇ]¤ÅšqÞ¢úcNޏ*<ÑÙÖZ{õfŽz¤ÉqæUΰ*ÉÉEV¡*Á •sÊ­2úoåóçlþÔ¥#ÚºàšÔ@C&šn>5>±™f“šjN¥åtÍÝŒôI€ûp@ÂÛ«pG›3šnÈ!©IkÄ@ë÷Ø~¹ :ì‚tÀšµªiK}DMÏÆÃ5™Y¯.óÁد®ôik“ñ_=6(L‹ÃTÈH yã#ù=c"‹©HL‹ÃTø¥L¸3¨‹ -—Î)R\"‰ñî‚Ùï»Î8´®o‡³ðúy[_#댫»Æ¦¡°º4sÙS´fkQh;{êpé°v™<,m¯W×gmÜŠÖZ¬}áèš1¸faà‘h29âôÜeaøøÙ%”áì–{}éÎ0“È`nPüuñ!N,àñ‡Ï”ÃW¾P²¡ouÂá“¿ûÌC3lšaëÒFø¹ÏMñºgŸqÖ1ÂÔ €°tžþ‹zôkqêÉ/^ûƒž:ß}ëŒ/þõÕË^ÎpöšÏøêocxª,Pƒv&§‰ÀqMð {K÷…Ô]Qzå«h]\ãÍßøcwåÊ>ÿyuÓÅ4ë{Î@âÈ÷¨ØË•|«}嬾Ûam§<sH€ç‹Õ{¥Ý>çnûD/mÙ6œÙ3NzÍ8Y#ëmégÞ.ƒ¹)] bt${ïÞ¡=‚lÕÆ+Æ_1.f‰9fÖǘ9<Æà0’³`&áe«õf×T|4›…²iðƒkl
-áà©Ô0i:œÆN'7Í‘Ó4&L¾Ats;Å“¾9!k×KÛ÷x|À!rætr|P™öÑá©gœAÔFÈCî 'Ú AÔ˜8*}Æ1”èaò"WØŽçÙqº×€â‰OÆÄaʼn÷ÀáêG’öXú#Y¤C”]íÌ"dªd‰óijѰ’,ž7ûÅ,ÑãÆ2­Îp¸Xâ: ¯Xã§kvl–kÒå*ª°(Ã'ç’µjW*­UÚÅoˆ4Wýa6¤•kËÐU(µ¢MnD4]GôíÙdÂÞ1ùDvlPgï«blÚâ/ãÑÊuÁí»làŽ÷ð#.²µìÙÉÖΓdØn¯6BŠA® êSIÈÊB[ÒÐÅDñÕ@Îò.ÇR‘Fq61œ“Ç*—À¡2jo¬›NýX6â6ùf·ŸÞ£®VÏŸ(ÕF/Š?ƲöǰÏðÇWŽ@½7ÆÚ#wþ@ì‚áŒFÍ2TaMÿ"ï!jžH
-4ò`9ŠÔ†˜ó¸‚ü?óû­ý<ŠÝ
-àRC'…p:"؃‹ÅÍ­“÷¶±&˜k­3Š96Íä¦Ù‹X\A ËßâKü|¨¦ñuOjZè¡mIÓ–›
-6bÌ
--FnÓ¤XbMß'qÃÚ>§Áõ™ヂ žD,ð ¨ô²?z[
-ÆhBÃ3ØÙÄÞùp‘©ŒícéñXξV˜l},
-c%Ê¿œšPDE_œޤr÷
-/-ZøSÇÅx ¸fxª‹Û¼á‰p””‚<Nâì&aôzXN½[=Ÿ:cËc w
-®A‰ 3°ç1¹ ?ô铆]
-W ÃØÿQ{HÐeæ"Àï©ñÃP$‘þã”óîKîwÙꮉïkKëf0ŽcLk;K•ØíÄrǶ»&æëØÂYå¤{Š•òû2öÝm`z[}ï•—ÖÎl¬•®16_CôÒ*©‡ó´ÿ医Õó[³~­ï8ï®Á3{µ­ŸyÛûm@sqŠh®û/6ÛCƒhÚè9 ŒA9Ýì&ß!Ÿ-£êÙ™©ÖÆzŒ‰G3•»jò]Ãwí!Aá_À`O*‡»f°7iùUeøòd¤p«l øé:]ãpK×hTÎÖWæ2†ÛÙá¶`cG§o[ƒÙ¦ž#zÕqu7¶\EŽUù©#l"Vƒ¬j&÷q_†zîõ: 8)r‘Ûò+ŠN£ç˜XCìánÓñUÖm“òÀ¹»|Ÿ”±B÷àýÆàãðo ~ÜT÷Læiêƒï¯~n²JuU4jšOüÒ¥
-n¡LLh§GÊE³|ËpÚ\8¶Çs˜—dñ ޳îÌ(OHÔׂrÆ%Ž#Jg’D؉¸É=Õ0JÔÔ¼QSö]¡D”*Aþ–A¢ é ‹:' šP Š,e–G‰ãßœ:ãiâ, ç£ô`[Þ/ëKBìýå³'á•B{ÅútN=Âd£x<‰ÁC€Á©0°#$vœ¯3À±).2® 'ÈœxB<8Ptš¢æ:©R¡• óV²æµ_'ÜÔ­üD& ýFlÃÛF—'mÞlpë¥qM‹hô3¢,y¿ŒÅ^ì£ÁqM7l㛆;ÓîØIݭܽ¥öLWÔž/…®€PtÚ†šÝŸÓãËJ´Ù|—x±6ë®iCUé|»}ÂÑ*|ÚC§kðtjAD žVètë.ëµ`G’ÇÒ5ˆr»w+š€äp`׉V€Ø’ÝDp¾c´Ö|v°^wo©KŸnŒë
-ÊáNEòܕŔ½)-G-õF¨³Ó®$­¯˜”ýFÌ
-!ßfšª‹ü¬¦²°÷Šœe]ËQ#èq»ÕyÓ/àlÜo¯»Ÿª®k\KÍÕ]ÒSÍi#LØŽÑr™?î’ÄÔqÒíñ!û]œr|ðq—Šº‘Gç™B'¹Ò539ÇW{‰Ž”||ˆ~WäÙÐÆ~æ÷Ÿ‡¡ › ÚÐ&ðÙwEb©êî_ÓMØT¤6é¨W³þè{~kËŸ5<@lV’fT‚$$ÖW,~œbô,Æ?“8TÌ€~ÜN~Ú Ö€a×Ä §¡†×PˆŽÉÙÆ4of¤„ «xYµµÑñ´“MGIÆýÖ“ ·Ëû'8x°`:>’(U‚Ir(Ì™¥èNŠÎ¤Õ+Àñ=Al¸d¦Ò+°Ù‚'æ‰}0É: cÕR…’½ÿh;©àÙK¦½Ó\KÙÏšB°Ûðà.@XïNÁxë¤ûw`KÄ()iƒ&ûÇÒ$JÜJ•X»T;ÔfH”Δ®lwäv7ÚNhÈŽâÖàóEΕC ÷«ò·ú³nhí%¡MÈ£3iÕ'Íz¥n†ý­ßÜãnÖYãèåæÏ_a…WðÕç• «Bû‹'˜%šÂ€íý†ˆÆ ±*™òòÞ2Ol—}WjšF€¦ì5“K‹wÖ SìÍ…å¼p” F­$uCPâÈYg,Z¼ˆ¡ÃuÍÚ|f5…ÙE­“±vÔ[s=ÎŽ÷ÿE!dÊOì´A–“Åþ!÷ë¬<Ã!óWg‰èž±Rn0·«<þ$öny×Û„±×¬Úr£|ÞâÅ5npaÐÈÉÊó&ïY¶Ã°Û†ç@dà ܱ±¯µöŠj±`Œ šØ\cc³V¶Èܵ §ø
-õÆKÉéHÖ r`ËóÞiÆHÊÙš0²IòxjUƒÞä¼7–Œ¡Þá\þÕtdÐÈê’-ÙrôIþt9ð0{ºÃlÚ5p€û5]ot¸Mœ»³¦7þÖämÿ¶Ì!× O4’|n ¯%×Ö
-¯>0\³§ø¡­œkp+Ò3K½
-§j)×5˜õ§µMá*ÒK…#6™/Ra’}®‘çªÉÇïû¹¢¿È? ˆ˜Í=
-Å·`ü·|)®1"Yh¾çˆ¾‚ô¨gDÏ5x½Åì{#“š¼¯Ö&ñÑ…n2f'ƒæDß N:Ä ¾Ob¤°BB §ëﯦ© 'P–~5QýÕ†6 E†žl.r7Yu˪ùˆáÈ=b=š:>ÝàÑ–?]Çœ­é†Ù³1%c’»bú¼mü´°tgTrWÍŸ­e醴µ:µ/µ9»×¢Ûqü«4ø·-M÷¤Áo£ÇGgR"HظDëK°8ŠSŒ8EˆSl8E]gøÄÿmY§¶ËgØ©Ü-ÓÕ£eÃnåî0bÕkNnÛ± t7Y­9K2X/·,Z®1jU³Ö-Öš¶Ä²¥¶­KEZ  µ­·§ñ¦‘«Þ§âú UÌ1¹6uí»=§Ým&ºc¼á`!ùV®í.c³µðmØ·sI‹ÍÚkéSg´6wcw‰Ë7=ÝÑøâ<{­¦±Å›û2¸uM^àÏúz{ËÅgÚÒæ°BX¾œqN*ÄÖM’ZxÑdÇönÁÑ0±¡±íš‰îYµ<ËP·yÅï‰:“šéªé©=¼|¸ ázð6 [ »~ÈhãdðE–szÛ]~HpEl®t[ÐVTÓ‰»„b½mÖ`Qî˜ÓxÀk׹ɽm¤ÛY²î>7Ç=íb©ñ¡‰¿ªeÔà¼- ¤^|Ábæë•1‚¹é­Ãô&Áœ».4¡z’ Î5“%]Ð Å›³s5úk3˜é ºàgÇmç¸íx&2»ÕäÀw¥-Þì€é‚;vI‹ŸpÒf7\—‹Œ;Bo#£êè_ë@;íL`«1R%•ë;ÑÏvÃ5ÓQ'Ę׺ »]~]Zm"¬z8FË#ö¡ÜfË’ËvÚt–] ’Aû\ŸôÉ@Õvíñäa"-›Üa5—íF¦b›Â·ÉgEæ’.;–æ Û¨K34ÕËÚkN\΄ätfÖy²ðÎç6#µ~«ýcó^›ƒ·y§ÓäPòSSCÑ Þ“¢d•¡äF~’uæW5ÓEÝëw\{‹57_Í„âôM«<4ô¾{ßu=ëJcÛv¶_]Ö›u>‚k?]ñP#Êû¼÷|„9ã̲7î,ëPóõ­2ÖGcóëq|¹rÞ¦:Ø–6Œ¼á¶î'Š“OhGÆB{çN{1€\Ö¼èm
-5müKZØi’«Jô¤q‚KœZ|¤œWèÙ¼›é©ñ!§‡Åïbš,Æòܪè–*¹u·j¹ó
-ày‡ùÀ«øÝýôú› ¾P}Ô6¼Ðªà§ù_@±
-°µ˜©fMÏÂ#7/% mØ@/Eœ ÙŠ¶œæI^<7Ò¢‘g½A u–gIÙÜ'ARb…ú ƒoM0`ÙVZ«
-öUmõu¶.«Ym]°Î7u èï¼ÂeÃê¶ëYáEé¤~ [yÌŽây·Î ÷¸±•¤Êþ©Ê„D|ŽÅ€©ù×jýŸþí5¨ˆøO-Aÿî¯vëž²>H#ÉbÔ_0®ÐÒŠ—vˆSî´ Úõâì¶ø&â,Z¶zè®»BC´¼šªÌ•
-m¥N/,8PÂ¥£¯ÛÛù
-žýÓ¢Ûí?ª×nYsî²7eé›û˜m m¾·-ç¦Ôœš×îé%ŽÅõÖÖr0ñÑ™er*ì>Iˆkc{/ìÖ­¸"²\»¨‹¹iìG\>Sᄅ㊺1»{¯Hiq\—þ…Z殤®äUÁkSö]9tE]Æ©-[5ÑþÔëG{±…&Ê©™Ð–øÏ6 ³1´~r­ùº÷$Û2^sV
-s Œ»šGöÆ»ž|AyG· MËôo\Ø0
-±Q™BƒÂ%Pð{‚£û“þV+¼ç”ÝJŸÃ>ÜÛ¹uª¬¼%èxíotêã–nßÖù
-œþ¶ÜVû•-«Ú¬énEÓzæÕL+Ö1¬aBúå'Ù¶íÊ•ë®$/¹ÉJ*ë´®QŠËSf´& ÆÇ%« ÆÞç>˜%¸W+L³ôÄ[óT:žÊ@Žåü=—ñÛ—‘›Ë¨îæË˜ÁˆÑx…2VC©c£Tv :ß`›ËpÍs€±);Û‰Çeƽ ÔP‘Œ› ÆÀ÷p¶E[ÖlÎ)/®IK`7¨ænMcŽ’aèc®øHrz·}6'ÒÄ›‘ç´fõL:²¡ÊîCIƒ©"åj#€~Tˆþ‚ùKOÍi´×Óh©p•¸æ>%iÎfØ~[Ü=­Êwë—wýt8£ë Ï-NÕüÏ(¤Ñ׿õí©÷Þjb‰Ü¶^þ„;»+>½$\ïP½uKøö=ázS¸3W…ëeáê)Óß.iéÚ$­&E+\%8SD5Fô)Z‡btˆ‚o ú]ÃÞÆŒ»«Ãþ„·˜›ë®¯­7n?6ôÝ%í2öN‡Þþ±|ß ~½¬ÝÔ äÔ´!¼6üJØÞOü´;…Z×Í ÓÖߪ˜ôRá«°B§b«Péí ×sZÑÕÊ/J'/üع$×UëÞn¶ö~`»æûtê½'W• ºÞ“fú<R¦ÏöªjDÙ“®tÎöéPù¤u.Έ|×®q ¶ÏìXáöj䕽5:“ýšâÖÊÖÞ͵ÞÉú{Bqâ‚Ћw&nX`xâ3"D Wf(Þ€ñ T!y„å]j”„^BŽziÆH
-Õ\$ʼnm¶æ¡­…ZëüT£Õ¥ 3®>ódí±Öé¬Fgà̃۸áº9®)4ëÝàh¿er¬w^G”9 Ý_L€Àµê» ˆKw†#s;vŵ׆G>ÕèJ¾ñ8¢ü#çµMcFl ó­á'bõùâÓ-μ~à«ùÎ
-é¸kmcÍ!+þrjYV6yÃa'å°Åf«k #+ÓHoÙâ2ÁÞÖÜÄgÞœœY­ã42•T¬¼òšpÛÁr›cv«Vƒ™orÜšç®s|/°0^e½Ê|'ήzPþ´x:ó¡[Ý~l¯$h}‘w‹8Íê=S»…²Ùí¼øÞzò°ÆqBEã¢ûœ:(U §Žèí<ì‰SV×c jö%ŒÁÁË´ ÿ˜ô€Ï¨„Bq%4vÁ Yü€U‚CtiyÄì‚»¼$ˆº¬ë8sõ<î¦ÂV&&÷‹UI-”Hc¬€òR´1û?'©=ÑûƇiÙß=La—'o›öüº(.ûisæ]ô~.s¿›S?›‡úzx|xL¥?»¡¦
-Ф•Y~Éð¥ciWú übGè Ôö,Ÿóè·|Î µ4aŸó•¯äõ²öÓí¯TS¿ÝýUïÝ-‡ÜÞ ×8ߢٮq¿µî¶ör{§OVUL­êfurz™ÉÅÀ‰5^;êM%õ\oQoÝ®ØñŠðÝ ·‘dÜéåÖôó¦j6«r¶øA/KÎÜ7Rˆ3º¦õ£ S¹ßæúq§”D&[>–­ëd÷9ÖŠ»­ª×Ny þ] ÿIä`ؤgb{/ŸïìQC˜"ª§D¸SJ§}Ç m–NOºë.Qš7§°ƒ0ÃutÇw9+Öï8`¶²„ÊZì¹âÏŒFÕL†Ï-Æe×µÞº7Ýr×l1uóÈ›66Ó>kî­™gYv‰Ì[Cãc““ /'týãü‚(0UiP´…z?¯ri‘¬oô¨ôœùÍæ~«•2£GÌlp^ùTF]× ÇßdUï±jg³µ&¶8¼xþÕVxŸóCæ@vª'à
-׌›[ùçmzè5îy½c^ãŽçÔÏ:Þ­o®>t“5`YeÀûšôæàsž¹7¹`%0SÒÚjNXÉ
-k2Kp æ¬>tSsׯu£³þT¢56—ÇO:u¨2ÞTêK¥i«î,wÍ´Û¼z{vïš[×xZÞ;³Õ²¦Àçyu&÷ýõy•™]ßé\otæd!’r£½Ë¹B-Ø$p@õ“;˜,ö8³NSدá€
-7­fö©·HÜqx½Aüúýà[lÐÏ»™qg¦ÛNµõ¨íg¹Îq;Ã8¿®Ÿà+³ÛÎíÖšåëL˜><šºÓäÙt{E[À-Ï×eåùÊsÚæˆ ¢9MZ¬Éæ$69ˆBDÍ‚a6NøËTGz¤*|ŠÔ4j’f‹µÔzÏ@šŠ‚ØÄq?»¢çi›9¹
-õ Úã£Úb§*î݆¦øˆž(è¶’è-ñnñºŠèôfU«#¶jj‰zm夂dT^¦Ë*)<ç¶ž˜YO\iŠ&LgÏ&¼££Ì9®xÅ3]TÖ¾Aê rNù¨Ù+6
-ir@çc¿áÊó‘ùhƒ„…,»È ÙÛ`¡a“–аš¼¶]ƒF<i¡L“÷f¶-h86/–8ú¦ zŠØF¬ÞÓ àjoèwTúw‹y¶˜lk©n­™­Mrk3ÝÚñ±7»0€¼À!R8Ú]ÓwRlø@«NýÀuíB,J!-¼ñ²ÑúÚvcZ¸¯S¥Á‘‚U‡¨ß-
-3µašåM»¤½O‘ì^mqÁ;K¼Æ‰=mÍB_ýÞ=AL¼&q­‘Œ6%Àß›³¬yÕ–…Èó&mS[½ª;¬íùýÝ'ËÐÙ•bWÏj›Í[¤Ç$žß;•—D„zç® p(6oÑ6¤/Kú½=¨Í€mÞÛ‚Ã]boe#c4ŒmGÈn=mS@éÇMöÙ‹ÞÚÖaùØÚ××p93Þ¹í3£9Ú:ÚÖyÓ/Ô^p°ÂÄÕ“¶£­„ŽN©¬`¹w®?W«îôç×¢áïe ÊÃ#m¿ï D*À:춺E“ï~½QŸ¼ç_Ü™°ŽóûïÅø,°$ÓoüáR¢õ>ÿÔ ûòç·r?–Ò
-Uàá2àVL²4`ðQˆÜÍRkyAŽe³d}ä…–G™ øÑ@v"À‹0&覴<
-y•Â8ò³SžåÙEhÁ¼pË2‰üýPÞ
-gNy’57Ëòšã4 ¿‡Y×g\FYàa–]"û8
-ÑÏZÁ"à<È/#;gÙ’æW\!–G¥[‘‰Sá*Ý{€¤‚ºÓE`ÚÓ`n=WrÔ*æi4 "ª˜T/RŽ\AÙëeh˜³¡Ö"«Êˈ[¡‚ K®ÚÖ±-§Æ$c;ÓËBapà€w qp/»u,S:H½€SðäêÞ7s¥s9ȃ²<
-9-21a„%͹›ñTVqòµRúþRF ËÈ&âN³̶Ê·¢Ç™çvŒ…»‚,0ÑJ(GŒ¼(ê©qòQ7Ø4²ë΃n°!_Ûa¼˜ó ô¶òÅð{aŠÈ[fðQOºuËÌ9ÈFÙ‰‹Fìg=‘FÜ4&àœAÖq¡dÏ!H€‹qÇ+r}ŽÃÔVà ÕQmì-8WÌrø•Ý›{d]IådGuÀ>1ëâÌCÙèûeÅ$YÊy¦s#–}8ænÉÅ
-L²w9šÉ#ô丕LµÞÂ9*ÊêDyr¾õÀÁG®`œhÿåá½ZkÙ(k­ Kà Ëã;æô@ªÎ8ÈìL´ÿ,ÔÙÀ€Óެ A¹†N\ F/‡k¢Ôêõ°BTW*¨{Ëä¨l)/é[‰ª˜•}Âk) 'Lô*=mOa a¢/é7c–>’œÈw4~šŸDda—â'å¹²O×ñ#¿,”ƒŠ‡®àµ"‹üÀã<§T'ü…Œ[:3/$TH„(Rð<OfR½œ”ÀWæŠòÓµ`ç©`ô†]gÙ:g2«1sÏ"Êç@«Dˆ(ÛaaQ!£`ès]^à¥-m'YâAÄi„½i3ˆcòæIª`R 0“
-ılF"ÏσŸ™¸$™¯"÷Œx\â³^Ì\ÖÁíF¿„‰´£ã¥ åVݹÙÐæ%MüldïEÖfbe˜üX·¾q -F^î‡Aº扷͸ òÝrbñw ¢ì°¨ë.ÃBSO³’R`â””2K‘Hö²oÎa˜ùÙQ_6ó&‚Oʬ îJÀK½¬mÃÆ?é¡Z¤"ªu¦¹`f2WãäeÄå4)Kœ‡"J˜Fù~a}^]C‘,B–vÁ@ÑgðQCbûGåIùþhX°Œ¯y8çtƒF™ˆƒÑ½’çÖ$ì:ꉈ&žÆ<x»,$R,®b,ʱ ÌÄÊW! ¢/ƒ3y­
-îT/òé"›q–
-æ \8±¦›³Ñß‘(Œ‹ 7ïæ XSQE‰¢gÒ¨DuëWI¨†ò`“~Ù'ÙuÑTIJÆY™$ÈB¬NL"„Y÷1”7h\£‘c£@HV`¦üAñˆEt’9Ð6TŽ™—)¨lj61R&yŒ:1’¢”b‘‰Aô„æ¸Á—6 âB3Ca\…’uáÜú–¼ŒVÌDùvÔ,MFf擤öºhI´Ú ØV¼#YW"ù,õÏQ¸
-(3xrVµ7‚æAÁ
-¬3r–á‹BÏÚJž¢“‘X–ã èŒÈPpª‘ú'hÀf27Eƒôs… (ºfLr|ƒeµ‚‘~IU¯­Z!V@ ƒ}Zõð™ÔÊ
-/á)#Àw´©M³ÑLUSr•GE#
-1ˆÊyJV(Ùàë”b9Mi#Òìû¾Ú‚íÅ̰˜ß)9nàÛ£= Q+˜lrTÅ9-
-hOr@(ð¼rÿžµ‹¨"4J` ê L\¤½sNñµgqE$;„å”Qq{Õ°ý‹[~òÓ‡ßþ÷æšÏï¿kŒÙ ‘
-ŽÚccŒ¼Û™ÊÈî`zŠšäËÖÁ ýUšAø eã«ä¯[2
- G[Ér­äý—1Dbåö¡òÎ2¸)l8#Ñ2xŠ
-‘ûVFhèK‡4?Ð })RðÀß'¾/ÄÂË€("qâ+*xVÉØ„Ì@7"œi’A+ÖnF§ã˜'nŠôHÌÞKcáz£ò$†ZQ?%â0K©úÜÖ6©‚˜t‚#ޤ—<IYˆ¥ÒÚk§Aœ‰uÐ:ŒD<«©0ÞR:9ReõÓÈ€ Fhq8舸ŒsØ2Fq°üL3O9šä¨ÞB†®ÓL‚ìKDDʉÞiL\‚ï;6ᛆ$ÔB „,Д/ܪ[3~EjÒ„ÀcÉW†Ú
-ŒÏßWæb™‹¨`tc–õôý"k,ò}RÖ`à‰;;U
-üâyfÀ²3ñë–Q«À›{Ë£
-˜Œ6bàT/ŸUÔÞ<H½,›R½ ­G”¤¥½„R"qŽ251Í£Ö;YÏó<ŒZo7
-Ú<À Ÿˆˆ0P(ºbþi’U>ÊDjû¶¯™ŒK4"fÞÚ´™05€v;"Ct<×ë³T”kS#âêLîïèËî 1{ZºãÁÈ‹0#õ–,æÒ…8óDŒ„=jí˜pÀ}32â°¹31KÆÙT&™2†à ÑÐÅ
-±¨‹iUÉ~ËKƒÄ ޲^0*äà³0AVýÀõ”a±$ –^áNƒïšê¹Zú>< ƒÑœ>“=AÇÙ'­
-ÀØ)³0„…EXx
-¡ö"’]ˆxÐèþÀC;‘/
- .ïBF«OîøÙ4‡Y††?¨`œdrÁË*(;gÐS Ö÷×L{2“gîYPY6’Û
-1输â¸h½ê†Y!3?ga{²®"±ÈÚYÎÕqÔ
-PW« b,­Å¡Y…ˆ6 ²¡—3]˜&Â"–‘I³|¿ís C*ô
-e €À ‰eC’f¡C!E)äl\íé@ý,ͤ 1Ë6…r¼T°\ P/‹¹x—ã©Vˆ£t|b"·`b'/"GƒB.Ã5ñ³è¸EÍšx›H„ªÑ«&]7
-|F½,ÚzTyÑî.´ùÅÔda8V#^uïôrPEت…" ›\뜸·>ÑI…- ](k ¼2=AP+Ai\X ¢îôðFiäu¦ÏÒÚ)è†Èût!²©Ï"sÙ2 h€9ˆˆÞ’´y¢f!N‚e@g'È<Lºìhy
-’pÇÀ‡k 4Ñ,£’,&’T(ú®õ(ŽÌq%+¯gÝ'V+"†fÃJRo÷¬ÔËÜŒÛÏ"M+ǧôqî÷—
-@»“z«ì)´aö"ŽäIÆ#²@¯Ø^ÌàÂ-Ðó*°r†-Ðê÷—9ˆàDzkŒ.ß¿1
-¨$²UË®:ÉDäEÞ5OA6žóHNºDŒrÚ Y΀Àš7$ ˆ²ö"ƒ ÃÒŠËÙ8g»N¹Ö%ʰ
-ü°t
-d=mÖ(›uEæâLD¼td¸ªH>3,S•ý¦Åë÷½"äÀDD=…ñlä7M"}Žº§)`L+ ª˜‡ûŒ’ë™Ë)¢»ÂY€aCy6±Ý@ˉG«Ü‘±A”ç´·©¬ ÙDs/Ä
-àH"‚ãŸ0·È¤@ž+{/ wL‘Dˉµ±¨^™¶Œ¢³JH “åxE–¡j³˜Ù€LRCÌVFcÍ(f) sãZA@}9ðV Þ9‚EâæHÄ4ª¶¡â`!ËÆ%T\°[ªr£‚Ìt€äd/Ñq]¤_öoLiaQf«JB@Vù$r €8Êú&·W$V™-ŒT‡lí…àAt 0`aØvÅO"Q²œ‚N“s–uÈĤø
-–C%ZÔ)¶" %@ÛÚ¯ žÈ«ØÆžF±@¿Ö)%’EèNp~‰ ->˜mLVÆÈHf³'r¼VPq2ð 3„¾V€ÑY<ß¼ºŠšÝHäûœN ¨<0©ä)±ëêfq¯‡I„u‚@r‚fÆ“Ò$F!x™|=G*cÊ×gõ¼Ä¤Påü–%
-y$w>èhVDô¾y‘i‚xc¯€jY€ÝF;6ÝDPy|×ÔÉyi¦¸¡zfK½UP¿ƒBÌY&an|pâ‰ôöûÁ™AùÁŠ9Š„CTª ï":LJÊtƒè Òe‘wË1p[¶Ãà¥eA(S2´¸•bÚ@åq®-0Zû,Æý^ÒªÞ¢!dv³Cµ‘„7¨œÇèÔ«íE/-Æõ€ØÙ Vl†…A+îÈ.‰…¸¨c–añ¥ìú3Ǭ,’‹˜ÜGCè4Ò÷³¢BfƲ9Ð-Ì9Qˆ‹AÖ ËX°<³ !ƒlp£×*æ0HU$Š;<dFT’_FÆfX rì'ç
-*P‚èNÅî'ð1Éôêg·—¬ª…T0M ¡|ɵVœ—¡YA¡µê³*&P
-š·gO¡Mªì$•”óHù`›]>{c@YÕ‚¾êÂÀ¤¨Òƒ¸ˆ"ìþÉ:0*ˆZ‰ºV£ŒLÔÈ£—8U±¨ 4°„³£ÕX¿²º‚³—´*‹7ª¨+…Èçtæè ©€EAã
-~%óeGq
-»XA ¹GÙóö†ñšê“Ì‹â-Õ-Ø<ZDá‡êÑû5“YËÂNH­Õ}YLÔ@œ¥_ˆ4HµÕA5ÊÍ÷Ô,ÉàÉ né˜j@*IúåÙD‘1>^@®I+XÔ¿]È¥‰wâÖRÇñ>C™Ü ÑM|¿j>ÅT„®{á6ry Jƒ7fްP²ÏÚ9¹—²0Vçn"–ñ–®eYØÜ%j+«czýJ¼ÌÀ~0­ê³ígéYÑ‚4FC‚Ì Zõr—\SsFaákI|уY*à}Ý»y)Úa”x \Âα"T™AöÃEìBèñMÃ…Ð%y
-gÒŠ¥qºÌÖ oà¨/„—™8{}PýàûQ’É|ÁÜ"x«‘-ï@¬ÇòBy•èeq‘5²x‰WDôC8T¶Fä9J£¾,kÜXÖX Õ´
-&ž9iŒY¦ ÞS8¤P£•r¢Ä~ÙúÜgˆ*—UãÙÁ?s
-#vXê–&q‚ é´LœeÝ¢''oRdYÃ'}mAÅUZÏ_Ð}5 Ô2Jì`ÒÈ7ÜÃh¦–VÇL“T…쉖¨Ü=zJÄ*1E9‚1 ïtQýó 1ÐIÄ*ðüì½ x\Wy0;‹Är'$Nâd¼h³4£»/’lK£‘äelË’ly‰#f®¤±f‘g±cú•¯Àÿµ´)”°u¡øJ?({—¶ü…þþ†Z¥?;´<m [HHøÏ{–»Ì¢¹£mfä;yæÜ³¼ï9ïy·óž÷ÂÙ»‰Mí0“€æHf~b±*°ÛŽÔHC…ŠyŸÎ1l›I0W¢ü3K
-ñ[ HMN´T9NçE[¿PÈ™÷Zp>ÓÖV!JæXš2»K«*"JÀ¦*Û¬_•R‹f¿w«šQÜøÚ«nÙºÖÎc§kªf›]*…À³@d0ÞŒ€‚cwFÙA¸AÈi Fõ+TÈ4hm¦‹Gc›DD»Ûô}á ÊܹÖI ¸¾TÆh¸ôHp ›CæÒSÍÁXhø9Ub{\cŽBIÙ&5¯.`×([Gi‹
-ñ H!Ý#8¡Âð2CŸÀåK½>šåºÍ»h Ô©kB$Ñ´Wvl §TñP‰• …ÈÜ“d…M¢ybÆ®ª$´Õ<¤—4ö ?>ù¤1'À‰¨Q
-5J5Ì*€~é=aÍvêQT©£^CRhíž‹ æE5Õ:âPxb€“öÔŽT8æÆÅŠ/ d€9•Ò†fà¤3]1ó¤Œb€Jn8’Bž^vTÍ =8rFáXìP¦*%/3Dˆšš•˜slÆjòY¡?p’I]ŒÏá(#Fõø`^E‘­"Ž{#¨æÅtÕäö²b
-‹:p\œ¦Y$GÚKìðVSMý@ˆ
-DçÕâ5¤ŒmfÙ¼(¢©ì]PLO T,¦•cþb  zµB;0ã!0™²˜}/Yé TlI‘2¼d|+h^7…³J8øI·ª2f'¤“D“†Ÿ…bm…wI ìÓè­uZ¨ª*Ûµæ 3ˆ›ÀK*óàÚhÂîéeG+]6 »—ÙžÁ'¤P•Ù°Ca(T£æÌ
-»Ç°Ë"
-ÚôLà›Qð‚*N3Ki„¾B
-,Þ[ÔÍD%$9n.ê$¥.„i1=4À2œÄ¬‹šÍbº¾¨²Pzû®‡Ûš*Û8ÝOîýêŒ6±òæÇ×¡é  ¦ÚîbÁåsr
-ŠéI
-:ÐLfjÊ.È¢2D4(–8º¶øüƒ«[3O‡ŒX ƒW a¼ÌÎXZ"2œ@‚ÜP±bª1
-žx&“´XXH… ³3Ho×¢³3IV([]T¯ÃÁ.«Ëbøy3Ò­€2j”±¸™u=A5àÌ€^MÕ˜@7Ãõ¬ÛxäXŠ2°#LžåyÁ¡"ìø¨`|
-h:üÁ‘ó<‹ÖâX‚*ñfTˆÊ
-i#9/e;;Ç´Ådhä²9›¥ââá\V¸
-OA‡ÊŽ€9ÓÞÇ)£éÑ‹ÂÂO¬S9Kƒ
-k/SuR´_YeyÅ
-¥WÅÁ[1É‚bÕÌe¦I,-–Ê™vààOÆz+ŒR§:½Üc««sÎÉo:n´‰•Èšã`vƒÌp¶g É
-£MðìuMDì½!mšÂ Џ‡ÖæîÊø F)‡ƒâ(Á“ 3ŠôB¿ä“æ}DSË“•‡ J­ðDíIR¯8…^ÁYÍ“BzÕJ^µŠÉe p1ðuò›])d¿­i´JØùû­9[˜±Ü6¨D:f( BpÍE`Å"¸©±hš½£Î^¬ðÄT —žà‹¡YÒ™Lüpÿ b×
-&UÖm±¤øü
-+Ú
-¹ha–jø¢…™ÙñA“D—…ÙÅ«R8Yö%,gùY±Š%z>.ž,$Ù0)òÀ -šS°íŠƒñüYƒ 5çª`õ
- оÔv’0i„3ÖÕÙ±’DlM; K³
-”G¨tqTXÅ’S²Jå¨W‘\ÛÂI•yD6 ÏldTGº<¶pº'šýP€WȤÓ_dLSéÒ˜~)™d$Ã…,+Š@ß}‡ eÄzÙÊИpr4¥•é68v(
-ìà
-½Ÿmr¬DûÊ2KÑG—–™'פ­L20 bái°€EZp6Ny‹
-UøÏš«j&˶h›Ê‚sÀ…F»Ù¶ ™“U´m.mÛ…8Ì“^f‘‘®Kýp› *C¤'ñš« }’uu ¨ä°w€£î±ÇHÖYp¤ ~(¢Avâ*ÁV*¼¼D«ÿƒM>E5ï
-ç&ÓÙ Ùt'P9ƒ#IØíqy± ˜žY¬¶bE´%±´SG˜ G ò*è®AI8”®è@.V›…gØ€sNh¡6„l*™ªL ¥™ 46¶èÔ'¥2Ë;‹U…¡Û§I†ø;zò_ºØÞ‰­Ø>¤­ØNEP“ ¨Ž2ddhÒ ;6ÝÄOžE.XÝÚ—Ò`¹b{'¥çD—˜«\ù)ðî9š®Äî±Ê@WX k];æhsÒ²¥1wœÊ¦Ï´´y«Œpýè/Ì«lê’àâz£3­«ìrë>éDÐ9V1Íw^v:ÊÐXñx÷b<˳³Ì…½ØÁ "9-Í*ì€Tǵe(œ<’Ndâ©\<5ã÷“bÌÌ횎ÌÞ#ÆN Ũ›¦.󫯻©ëäáð‘tÌ€¯¡x4O§"™Ë =èñµ=œL¤Ð#?+ŸÊçŒl»¯³©«?“‰ÔˆÎƱŒ‘‚炯ë@*g=ƒ?¹Ëó<kã9®¹Ý×u<¢â1ÔojÆYõb$‘'u/Åc¹Ù…+ƒƒºZ»³ž1š5â3³9×(±ê«ŽSÿÉþÄüld’w‹Y<†jV@ê¬:*îça×ëòp]ãqÙ5—k€Gzê¼ÍÓùT LW˜u ­iÌÊPÕ\Ö5‚Ž6.0ª6™Ëg¦ò #5ÜNiêr^Ø85ÀÊ->#›O¸g•¬úêïK¤ ¹Åi*’5†2Æ…<ZX÷»´ Õªc˜Jåâ¹hIla™ÅµÇã ÃýFu´Yu ·¨¥òÉ£Ñ\äb˜Ù›¸á@eà瀿´àµqNcÜÎNxɯcnOUXC»uWÆÆÒùLÔÎDægãQ÷hUU ªŸ…IzÞÈDréŒk|¬5Û5éä|:ϹÙ4+
-ŒÈÜ ÄØl$–¾´ŽøüÂZ1ûªÁ¤Jïq¬!":±Gb­ΩD¾‚(l<CȵÍÅBÆÅx
-TêÜnæ«Y–e·œWDIÇS¹0u)ÕÂiŒÑ­¦¹ô¡EùêýL¡Jµ¡Þõ¼5ªy‡$õÆ \ †¹
-îÛR@ÕÕ=pH=ÎŽ_Ïjæœè±®q/\æB¶Ô»°\“ð‰xn$¯dm5žÌŒdâ¹Ù¤‘s¿RW­ìl[¹z7qÕÛ¯F yØÈÌ0“ ¤UË:ÖâZ¬
-¿«bê}¸¶îf¸Æ¨Þ5<÷wtW'ñJ½ì¾éª¢Ó¦ã‰D5C‰z^ééL:é\yõýE”ÛÁX¥ˆqûÉX¾ö‡k^’K»×hÓ5@$’¸¹ìzaóÎE2U1{Rõõt×8MÁKÓÜ»•IíÕ¿žåš•[˜™ÃÁð»Ä° U ®8¥Œˆë#ÑH"z8sžÕ G)×Ò)æ“ùÊö…³5YuÜ2vQ¸F/‹çâ«@ÎlP#“$’Š'#5K Û¨yèüš Sg–]tÍøǨQ¼^0L¸{« ­zßök.Æ=FõîÐñ^!Yì¹j´h÷é½p˜U\×úgc„ÃTÁóê>f ÉÖ5ã£z—­^8ŒS/Âè*‡á¯–p˜*8d½K¯5ã£Fq5f8LëPï{dͅøǨÞ5¼z ‡©ëóŸÆ‰æ©‚@«e5ZÃFÌXEÔœ·
-+¶
-+—M¤aå
-ÉòVUhk±ê¨yoBrwß<™®t}¼Ár½¸OYQÿùQ¼´"‘V„÷ñ=çãeô—ó¡ÿ÷ ïèßôÀ·ÖB¶ã©˜1OÅÝdŒy#’ U±Ýl-V?—r®ÑÄdç!EŒ[½1^‚˜:KS/:Ô|õâT/o”Hýjpª÷X}ÏaQïì ê“˜z¿f^Õö©söM'çÓY¤ÀÍW`\Çæ*Í}c˜ °•k †àÚÁ6WáøÆ¶Puõ­v׈TðŒÚáka®»F¤BÜ“±®q/^æj!]¥C×»È\Œ˜i$ѹæ2 F2ñÜlÒȹ×Û®ZÚ8G‹¢Xï`5
-©~]£XØÌsºÕÔé¶–Þqë9ÝÃéFøLÏLÆ0R=H3zâ©X|&Ýs1žN¹žŒëIg"©×[ÍóÆÕ‡7®™à¹ä<—Üêãæ¹äêÎç5×§.‘WÆ“ù\…—òÙWƒÕ_u:S\ãd$Ъ\>¶5ó÷„âØ
-ÿi6w9áÞÇMk¯~ w5o
-ž;»FîìzáwkIá®ò§Âª}‘kó
-><ŸNU(IÅ ëWKb°V­ 7ôô%O_Z%}ÉS—<uÉ- c”Q5 ¾´&㣡8yº`ÍtAÏe^oLÁµÈ˜«pên[
-¨Z¿:ê\…švDø â~E*¤W²#"Ö5"î…Ì\-dLµgu/4×dìp"ž‰Ä+Ùœ'3#™xn6iTñ’OvÖƒ«sÙé‘:—î•€:—î©sÙ¹(û¬Þågµ¢Æžè¬sÑÙ8~hï-õ¨ ­8Kl€µX9
-Šd(™<’N .pš?)3ñ”ýAÓ‘yÚ~4v99•N4µ#™ö&Î×þòRSýs´É
-¦9yý8ˆ¾œGE—|’ï°ïÌY΃ڣM~U„€&ˆ‚O“T=À‹¼æK«EtŠSD(T’Î ¸P/Ø
-Pš¬TYÓlÅa\¬8]R]h
-àUEs f/¤€á~Íb™š¢Ñ~mÅr@TÞgL攀ÌéšÏ˜Y8ÐDÐPDÕ^7Œ‹¥€Èñš£ krdN
-è"§ŠIåUÚoÑü†›‚SˆìÚŽ§€Db¾™L$GŠ OSÚ}~.Àñ¨ª€–̯£u p‚ êt=ÉßàLTƒBS䊎FóóeQöÑg
-†Š3¡Rº,ñ¾“IGk«"*[‹hµd´ÊÁ¨½5šEF³^ql! kšè .flIÕ¢Èó0ö4¢Û`. '¡‰Ñ$ ˆšI·f1šnNåEJ¢<§H¤+ŽÓÈ""ŒxM¶ºEˬIöâ0%gMG°Ú»Ðd M©*;³2ÀH¿¬&Cᶬb´¹MõÙÃô¥ x“˜€™…„¾fq¸É޲­ krlƒÙ )`¥ç·,ÝJ2¦[QT‘7éVÔtU*G·QEû_G[Ñð]Çê *^Bü5°Ñ-´Öˆ8„Š­e„“€FA´ƒ
-éBñ'³¯È’Z¹še´t–Îj•[!õL-TÇ]N9‹¬ëŠMþ#΂ö=Ò^GžS°Às†**ð^¬PnŒY¸è)« 4ªÏåÒNñŸGü©žj¼²±P
-kÄÁArÔÕÂ0á½Ú
-¸³عÃÚ{•Ñc$Ádf!t`Ak¯kâeëµÄMÏnlÁxÿªªú–^4[f1TÓu‰Î–ÆsX¨ŠH§µ‚Ù¢…l¶NäuQ〤`ÕÉêÕVèœ-V x :ï³w
-6›,+JÁdÑB6YX{]-«Ó3
-Ö0I‚,ÂG4j6(ÌÆ‰P³±ž®¦†°R˜{ÍZM\Ì«D “U «fš‚ÖEQ‰ÍÏe$‰u‘øÐVÔ8ºCu™ ‚@‹AŒÀj ¯²NI4-t-9@1jÈ\ÈPÐ'†Ô‰è‹ÖøPÈxU k¬h<ar²¨W^}%g`
-Θ “€Ù¡è;ëCŒÓÇÉÙòu ˆÔ#5™I>L]
-å-Ç.ýÁ_}þ[Ï<÷â‹Ï=ó­ÏýÅÛr#ÍP¾käâïÿÅÿùæžûÅ/ž{úO|ä-Ù#» üîàìo½ûo?÷µï=õÔ÷¾ö¹½ãµSû¶’q‡_ëûÿöñø‡ÇÿúÏÞ|y*Ä
-Aª58ôSÏ ÕÇÇÉͧÞ๦.Aò>ÞÇûxïã}–ëSob®>•¤ŠŸzS¿ëÙB©¨êßÚ­9T%á©!T ÀS¨*³ÊP¹„gÕ ª
-žU€jð¬(T‹†g%
-ˆ[@9uáuïøÈ'?÷å¯û_ÿÕ)PnÙX$‚ˆÈ:{áµoù“ü ’Y ‹,S(jû'f.¾æ‘7½µ’P¤b÷Žm­ÂÞƒãg§Œi£‚Ø¥z@Óí[}­ì;m²á¦Í·¿é÷UVp“u믻~ÃX;q¡œ&¦þãFý1•W°¬ÐC<t†±]>ð⺗)®[¢Yà"e¸³†èKð…"E—‹Â½
-'ã[NZ€ƒ€hÛö£#qºJï;Šºf þ.s!¦|€òrE$ã{’èÏYŸ,úäÒÉV("õÈ_É‚¦È‹I®égö oìÝèóØÛ_Þe‹7½ÿ+Ï<ÿâKW®¼ôâóÏüóß8S±Éù?þò3WìÒçÊÓ_ýà›oæíÿüÓb¡xåG_úãòÃežøQiáþ«}:_¦Mö /–ió«_½ôÅÒ­²_,¯¨ Áýù‡KµùÇ…Ú û¥â±‡Œu©Êqp«/fóöO•Û ÙøûÌÏüÃK.ÚüêWϼÝÖèåÖ§ðó/i³Íì—\¶ùÕsï0½é‡nýêKkô+•kÓÏÞÀ ûŠë6¿záC´ÑžqßèWÿõ·?_E£§_O½«<qžÿ#ÒèÝîV–|^|Œ4úŸî'‘Ò»ÑèÊ¢ýÏUkôîEÌ›ˆÇªY'6åUQ[Ü×WC{ÏP2?ÿÏU4z’±‰¸Ÿ‰ŸÿÛ„oüëFO=ÊÅÜÃ÷Oq“I<ö¬Ë6Ïü¡ÅÂ’n7ü’6Æ÷‡O»jó”Y^û¬¶üóOÇí®¹´€@cŸ+Ÿs
-
-eN¬&HÒù
-gq×]ÃÆo¼qãÆ 7€o¬|½7ÞÜ´ù–[nÙ¼yÓÍ7n,Swݵ×o¼iÓ-·Ý¾åÎWÜyç–ÛoÝ¼éÆ ×—ð®¿î†7Ýrûwm½çž{ï½gëÝwÝyÛ-›n¼áºõE7ÜÔtÛwßsß¶ðù¸Û}÷ ºM7m(¨ºî:ì¼ç¾û};vîBŸ;|÷ßG|„×9¨7 ŠwÝ{¿oç®–Ö6ôimٵ÷ힻPU‡osýõ76AÅí»ZÚ::ý~gçî¶–]Ûï¿÷.ðS®·½qÓm¯¸çþÍ­.Ø]ÎÝ­¨ê=¯¸m“müõ×ßtË[·monëtñ‚ˆ>ßåï@U·m½ó–ÍN¡ËÛïºÏ·«µ#À "ðY.€ªúî» uÊ ]wý·Ü‰ÆnÙíçIALDSUY8ÿî–÷oݲÙth¯¿áæÛ Ë¶Î.¨ˆx™®kª"ñ]¨Ó{_qëM7¬§S´aÓíwoC]xQVõn8yíÖUYD6o¿ïnsxææ-[ïßÙÚ] mooO®¡Nxø¦×™5ï¼ç­hpèUDUQ§’ÐÕѺ
-YU9ˆnÁÙrmí¤³Xd$6€th]Õ)/ÒiRGx5‚,Ù
-™7XTEÙQ2¥ò¼Î;zµ2XVURLò7‹ªÏÞ«Ì U6s6ÌB¢¬2híuM¼l½–˜7þ`#RÑÿ«ø$qGòÂ骨ÅI‰P r¢A8Áü×Ï\4H(‡A‘›GØ[«¥¬¶9ç%†@6Eœº
-¼Ï^P°R*2‰ ñ=¯UQÍýìÅ„%"ê$A+NfºŒû¤€L^½"ƒ/^ÿ•ÈÚ稅½ñŠõ¿Ê™ûQ擹ϽæZmÏËÀÊ´–˜ecéð,/‹f%ÀX0+FUÀ¬4.Y0*³š`,
- Ë̲€±x–€E@µ<}®[·ÞüTü\·þÚ›·ÜA?[6o\ Wd"¹«uÏ¡£#øsôОֻnÙPŽO?ë7liÞ;–|ô}¡Ÿ÷=šíݾ©düëµ›v ÄýÐã_ý§éç?¾úø_ÆG‰î¯ÝÔvúÑõ©Ÿ¼påeú¹òÂOþóKïI ìØtmQåö‡{ò鮨ó¿üòå—~ö­¿{ôt[Au¨üîy¶8åÍË?úÉÇjwT'•VêŽâ/¯<û/ïvT_ 2tÿ3T½mCuý¦¶*ãêÞ±æ¬Ù°ãôc TFÕŸ}òÑ-–k· <úä³ Þ«¼òôÇã-qÆ Íñ?½ð%à_¾ðµ· âÎ×ß²÷ѯ¾P>çéü™Ç›òkïûàS•îÿò…¯>º÷–õ×¬ÛØš|ü'oƒ^yêƒcw]{ͺÍ{*‚¦å''[7®[¿åÐûþ£òEg
-i½‘B0XŠPYÅKQꀶœWRö§“†ãŠýJ@Õ$4Cø®žÄ‰º Š (Š J Ù+¼Œ&¼H©pcEÀeg¢ò°^Iz7YSU¯AŒ¿ì ;ŠAÅç4¤{‘b´d<Ï/P ÷4ch'¢
-¸XCdÇË‚hƒ„óQbús©b¤2+Ú·ÐEAY X ð`õ„©&£¨¼¾@±½Gk ðå‹í
-e}ÈBãI¡ÆQ‹äº¨ñäÞ‹¬¢®˜Š- øV+¬ >2£š(ÐBvo"¶‰ %Ô2ñ¢Ô¾@¥¸_™tE
-Ô*EVÄ‚B5  &V1Ú œ ÓÁpf-´sy´¡EŠ ý!…`HŒ „™„íiÌWŠÓiꘉ °d£
-KÏ xQÒïPÔ¥b¥©ºYÈá4
-¨PeÉì€kÖ\ q BÂhÞN …HÁRÈ (¢ªšV’Èñtbx¤ˆQé§ëœ@¦P×e¢£¡Ùä5{!é@…üÞbA] IEÑ>˜³ÖX¶RTb`”¼@Óœ!¼/#rZ”h@[ºn+dkÀË¢è¬ ‹È©TÐs<O
-Ä"x¬‚.*¶T†ƒc‚¸9y"t"œ…*¬½UŠfS§>9Àé
-åŒ*Ïë
-
-7öˆ×“M#q”dÑ$é8óBÒ1ï“€™6`­šS
-„ÅÒB“ÁKæ¬k2 Ô«(ËrA!âí"RkJ3˜aݰ­aíð¥u]F».YPŒxZ;ºÅtMÂh@w*O!Æäg2”E²lua‹ ²@z•JGV!‚@5“u±b. j²êœ3He"S·xÎT{!›3N²Í^× ñ^P}%ç
-%
-<ÎLGâuEôÑ6<ËjÔ24€ ˆ´PÐx/V”¨ˆÊ:¥@4
-îR¸Öm#‘Üìt<32¾±|<g´ÓE>9² Üg…DÍþÛIà° ÆûBMLÖƒ­b*+š.ËT¿%™
-<³1°‰OºtŽ*Èšy3›¬H2Q/9)àG@«'*T%Q ½*"¡@d ¨¼hªèH9ç‰~&‚NIÔ%œxh}š@µ>JÖ–…„(DШݵ<²UÐÌ D VAs+|ŸŠ²yá!YÞGØs’¤þ
-MfiäLãi‹GáÒšÝ !|ˆ½²•>­+ÝŸ’ itf8Q剭¨s™ž¨ybI2µ0d¢CaV©ïO18Ñ|²$TÑ$Æ‹,ʦí¡kxc‚ù§Á”mÈ"5a^gšhÁP5nù„¶IŠœo´êGjˆ9]ò)¾Ã%QrÖ£ä…)9»¼”|¼‰²ÞÒjän¢K†,U¼œ ™Ý€ÒyœGûnÕpî¢a– -ª,šº˜b±húb§ KØ^µ%m0¢ùqx^K’*,Y±²¾—@®¦V¼x‚e§AKضdºÊÑ}-µeÇþ¨Rq.æüõBœ5Þ¡)ÇÞ(!–…¤ÖÌöJ-°7VÈhX„Ò_­žTÊJp(Ov[wÚ
-Ë~*46›&gø…®:~ÅO„ÐîñVFƤ L ‚bBÒâ ”Î|4ê—Õá(Ûþœ¢°B9À°«]¶Ó ̇ Ç5¬PRªfv€°ù+r«Ë‰µžeÔƒ@•¨­·
-ûôã#A⨵®ª¢džY²bÄB)tè« éÔ+§ÏOÈŠYÈNTQ êjˆób6bïÕ*¤0-š ˆÇpìtõjMš ûÛ µÕµð²õZ40Áæyg•[— OÃ0Ç•`ËâØjÄ 5Y—lÅa¯,j:a€øpØù°Àqᢼ
-‚­B|4¡€wRämŘje´ÌšÎ;ºPe…EÛ³
-MÀp¿V1C#\»0„ê—|–ηã)Ó‰Ëß‘=Ózùê©N¢O…pØÐäˆqÖ
-G;™´7ÕÝ4•àL\ó£h‰DÐ.%Éå`Á$j"CZq´{noçÐnÃMଗùJMèù;n" &ªT© B#V„[ eUDZ
-°Ý.(F‰É
- Б”'"‰‡)g@@éŽ.ñ„LÔƒÙ )`¤_Vl¢.‰çò8*ã¨äÍ6ð&HÝí×ñët‰µòìÕ/`ÁU¼Ùa%øHÌ#–ää¯~Ä(­.ØXDKΣ10‹åÜ…¹XuµýR@Ö¬äWÕˆGUõ
-pœ•®YR-Ü)s¦¤ðóø56RÅFpÉLœ<Ùå\CôˆªrrWöñBŒXYHO,ß„8ÉåŒLjðáùt&7~yÞ(ˆ–·×IAÜüp>3²E~=Vi)˜Ù\Û{VwUk¦ñ„Q*?D`‰*æHå€/" Éþ…g„#¯EAVnTο!€³N+©ÜŠH‰Wx*>XŽdq1†°6³Vz‰b–Ž0XKÖxa15ËJ›„KƇ9 y6!=;À¦#¢Z°o‘騃`ï9Q@2iøT` t = |É*A(?GHê‘eë;\zH†ø@A@ŠÚÅ-/ C¤æq@Á†²¥6h<ñÒÀ‹pTÉTH±cä2
-á„€wl@Š•@@y eŠ ‰†§­W©9­z“•ÜMECZaý #‚_ŽGÖ€ø_3!¤†hÑ#’²•p("€²¤huR¦Øì"Ý
-ãán5«Â¢©Ë|}$~€Û–á5ŠÇk<^³²¼Æý©CC0žذõMK>y¬’Œ–
-¤ÙPIÖe Â/MFÐ LÏG¢v–Íf¢Ö=›Î¼² @
-¦ùŒ½ÅT"#¬ÛäÜíða³›X$3W3«n̺j˜§æ1Ï«„yr”Ÿ•ÊP»
-ZjEÎgÏíXÀøð£Áéi¤W•å|CF$7 ³ä’ëÁI¨À8
-yžxp!à ™…º(ãS#d "&²*܆g
-6Ûji¼åôÞ-‡ëŽ[Àu×øü@àêAÁoÃòë˜W£¾-|Ç’@¶5¸3.`HÑåÕdežSË…SËrQ1·–PÑ­µ<N-OÞxò¦&ò¦öâF\ FËÛ½ÞážÇN´vü-+’ÊÕ‘•Œz-ÅSDzÞð!Š÷MD2óeÉV-@pþ ?nßíë‡äÏVš’P<;Ÿˆ\&?“À{‚²f, EyþùI±9a%šìOg⯼Zغ°<a
-»¡­’‹Ùuãüõb ¬˜ìr1PþAPEwûø‚ (n¹îö­É'.—“^\NáWØÝ"å_!L •³c8¹ìÃq$éTÍÙ0•Š6÷ÇX<9Ÿ0ÝÕˆàr¢øH2”Ò—q$fråaE®2èü2nònÏÇäù˜êô´¿z¥O€Wð‘´î$@ôÍ-‡ª¢Ê…º
-_¨«^)TVàÝ<•ô{;¦°Ènô•«JJA¥‘|"w¶o/Ú2£Uhµeú—@/Ãäq–ËÁTÌÊqY1QæR^އa™rmÛûëζc´O¾²©°¼i$Z</m³ð.Hü¬
-¥-''¬Ë€Nl*+_(Tú\¦}Ó”í8˜iTl²ª§ŒD±R›A`¬¬Þ0RuS´$ *î•ác"Çj\ްÊÃJ•,´:«„°[RYh¦[•&Ÿ÷±d±¬òáÈ R"´>ÏlOÂÐHf\8b¦_T
-êIÂ(J")°«ë•§„fIФGJå˜ÈðÇæŠ1“3ùp2ZÆÕLöL雃‡–€a+f^8aèQ:dl„ñ%™L=Û)*c”¼ÄvŠ@:ÀØ™ÄÎ6Šb9Eóò
-ô$k¨'@KM9Ew©Î€-êÔ(1Øf‰@ÈxÀ¦I·øÌ£b{mƒƒ³D«Û¸ˆg[ào2™CJ¤ýÚ„b›t=M uS¥†Éœ!)šŒŸíxVÀ1ÊÀ}̇¼•͈)^”ðÖcGbÓ&±™13aò YsPÆšE»´AÛ¤ ¬ªÆz•ÙËjè•#ȦIé\`;U4yX  ^5
-#¿UÈÎF(_c/Û1§Ý*°Qy,D4-K ÊhĄ͜Ѣ÷ æ»cL‰‚ŠÉàD¦ƒ˜©¡¾xü2Æ‹èr›{ª@-à±ÄÃ2˜©
-N °#’žŸ‡;­è+âÑÙöÂ÷‘áË£Ag:”Žæ“hrB‘\^:Æ~ã÷9œQ%~‹¦¯l>B—¶÷K&qÜš£(;ŸÎEqúÊI•EÇæãRÄŽš¢iâúkžìWRúúó¹4b]YÄi蹑㽖ºo>2od|Ùx2Ÿ 3æs¾ÔR÷E2¹©t$óE;‘ç]'‡¤cFI\ÑÈ')ôØX\&>•ϱ—evõg€äºW¡‹eèßV+:OÄ26ÿì)üÉ™/úlkIe'/F2ÙÛýj{Õ‹ìÂ4ª åÙ2õàÇ\LZ±³ág'•N.&&‘)éffXÍe"ÌÅâ5OÅ ¼ ÜqŒ¹#‰ÊøÙk/Óò/q&øgÂþqx®¯¸ª´Ñ»/ºÞêPµÆ èEóÙ\:Y[N¶rtØÀY ˆt´ÅÜ’ãŠï K²vivúRKã†èŠyÆ\nV/Åc¹Y7³J+Ö–íUÆgÖˆÏ̺١fÍÚb$Z1ge ßÑ×™×*!rÙ "—kH—¢”ÓJU³£“MģƤ̪u X1,-6<¶VïlçõµÁÖ$a-±5Y×4Ýck[«|­ \EnÐlmmikª¢èŠÇÖ<¶V'ø4[³rù46[[[Úš.ÊàðØšÇÖêŸFck¢õd­Õ [ÓyNä9­­, ~0¤©j`­ñW^ H
-¯®5.«®‘ ?¯¹ZŸÆà´æ×rhL¥s¹t2lLçŽfâ3ñ”¬ŠÛÔ ÏKç3Q#×­k)¾Tk’F.‹ä"K…£”¯¸8vÆh ¦ê²U†[($ÏûØ3_<›NDr†o
-nÓ÷¡  ³®7C\äa#;k†VâØIߨæ­0Ê2ÝÏ¥Òѹt>ç›!‘ÞDtt~4Ÿ›Gî^‘eQ.©éãül–[5œ¤e>‚ zù²flhÅ.gð}V\W°ÎX®®`¾bÕjºÍ°`¿ŠÀš5yÇBŒdŒ¬‘¹høÆ‡s¾ÁX<™Š'â¹ËæªÑ.Q]3ÊwÌÈåç}áHj&™1|#éy¶tmg±x>i[Ÿ³6Z,ÕÍP‚ÿSF†À’óYÑ}¦F2œHOE£Æ|>‘5—¼H{r0¿1#±?’Cc!øÌP?-Å&Íšát4’€ÑíuíÆ!
-FuNÎ\ÿ‘HµCe“SFl$“žŽ'ŒCÆe'qÔœ˜GgKÔ$«ã¨
-©-ÐäX¸K¶¥¦|,µó…!Pª U +`Úœì ÞNþ‹¤íñ¡Ù¤¢L–YûÏÅX~
-­ÏP:•ËŽÂ.,º` ´¯ñ”áËâ¬Ù…+GñyD­ƒö0¢Ö„k¶˜u”ê>‡Hw¡Ù Á"í¤]Žy¶#ÒÌ<D¿>64á
-8êMÍ=¦\àNžAžÛeÉ´÷Íç¡XâÌ™¾ÌΓ9‹gã%A¼4±­ËøÁ¼>»ÐB'kt7a™eŸ"žœJO—|ž9¶ÿHÿ¸0@<±[i ž87ê#Os‡r{†&\ÿX~W|pj|° !9q6tèÀö1ói£ä\x(Œ*¢E´sÁþ ½cßDÇCêètkTh?°½OƒƒB(É…sÛýýøßÙ6  ¡ýɽÂd²µÏVvn·Ä-šší5c»ICap»2@žõa(Ø5‚ÛÐÖl
-ºµï^ÿ™Qs>%Ä#F³ˆuìV¦-域 >ÔwbW.GˆoÏ¡ñ ¡®!±‹Xþ¨Ê8š˜@—ÃQwØÐ£ù®xž° uíèõzGå¡P§ÒÑÍkÛ µŸÉÙ%ÖD¬ËÆô¹ì©‰þÑñŽÏ)ó9øvޮÎMl÷"¯[δ
-ŸH9 @2MͽûC“ÁÞö]ÍQ¤r-Ê®SâÐ@ÿÙ™¡}=Šm/25H±)wÐb”a´~*7£ŸÏ´ž,=
-TJ‘ƒ›=C©ã%öXk¿:Ör04Ý?ˆ4‰éÉ=Å“µs®_Þö@ÿÈ®èÑÐÙø©¥F9ÜÖ?&M—é¢%×?¶sà`êÿoî=¸“ç•Eá_À€$Á¸ÑÒéÞ{hédïó®o}ç·ß‘Üd[²eà]÷î}γ‰-ÏH#M•FÓXû­mÕºNµ/{,- ß ¾k[ÝëÝ« ù¥µU9x¼Pjñá©D6.Pt{E7EôÅK°.~I Ö/L¯m{ ˜a’ª4›7+È•ø®ô·ž–Чké+´A°ŒŒ$)3J]V¬/wæ°‘Kßߣ-¨ašúÂ(È?½\­4>:È‹‘­1«½(~·û&RÖXkZY?þíaü¡¯?“¨ŸØU °¬V»KÙGàÈØïÐf0÷Û8ká­¼ÍןÕUðJ?³ÅƒÛóc¦M½~Xy-TÎB‚ª+M[aóºš<Ž%Kß¹§”W»ÃZùõ`0×f°ù Ü×{[ßµm¹›MîõýfpžÝk±>E‹ô[_‹Õæ‰Ec¥Õ¿Q{eâ>øÒDì óŸx~Xúªß¥ÏÏ“½J³w:­ìÇã5ÄÑͽ«‹fÍ^ck6ñ [=H#sÚ=£ñrˆºKî¹[+w$RÈîÿM™B6ÝèõºGO¿ÚË“üÞUÌå~W<ïŒ^µ
-ø/Çï[ø-ÞÅï/–k{±þ…I»K$Ÿ^²;¿‰/"n‰¨¼]Šmµªë¥|+[S¢kkýïá>[Û¯tnúgÀa; °.nŸG/Ø4™†Aysr43 Bª¶Œö5w+¯±ÝU Ão‰ìÒi|Z‹7Û[@±Ë“^¯˜ZTŠ¿¡´^Ù¼Šîæ#){õûZÔÔ{´•Û`Áþ«­Þ½ *¯ÃÇ$Žb± GHšà¡ré¢þ'ŒžŠw‰¼5ûXT»KOùã†rQPÖ÷7kÏëW6|:äï_T‡ S·Ž…fÂyß¾õ6ÌÓ@GÙzqø;ISô~ÄÈúö+'kûí«Ckü¶`ø)؇µX=Zk€YYiƒµ–sââzE¨ì'—3$æïéJµÛYõ®þìgi5Eÿ\yï¶l—ÇÜÞæSê9Ï Fz«  Síâ°Ø¯áîáÎip”xq9C¥Ü y!UßeÍNÔA½€gQ<éÿ}lÁ€mú§Z[­·FÖù#!²Z¸Êf÷?Þ²©Û;¹I•Òïƒ^{¥ðv=†¾6PI£’TþˆÜǪɵîoE\I p 9ÍDÊk8?àÞ^vê(•”ÿÝÑÎà›’ÞvÂÇ#t–n®àcßø¤e.gÕu´:7O“Çåp±iž²;'IúŸÕÃxÒV@úsغÃotXÛy\ÜÙlÔ~ëÛƒ·¾ýTŸ³ÙäëcÔùn¾žHÇýÿôÇ“>êyß.>\ŒJ+Ð5ÄaÛÁY: ¬“†z¥²“JM?,
-ßÈoÀòm÷žãF£ïî?ì•¢µé&^$…6Óo3«‡º*ß~¾„‰QýÏ£Mç»ßïù´éއ#v—_S¡÷m›j›É_Ç•BÃ4¾­ü*M„>§îÑ݉0迵­ÓôŒFÝá`Š/ñöhó-uqúKž8ÚMÞÛ B‰< j+”©0èOœlõ?#ÁžÐAoƒ2.؇ÃQwèÓ`â1tÜ ÷ç©t<8>÷fàqo äøt¹nÝ Œbtó·ò“ÂÝBpÄ/…s!¬•,Û«~ˆŸ_Ÿ<$Âÿ‘½{`FZú=1ÍÑL’þÇÀƒ‘¨ë|LÚ(uÅ™tG{°jQRTYaâÝÒ´Š:¸l¤ÖÏK˜ ÇH—¶}:
-–ç›Q©½ïw§F|B}¢ÉPó ë¾D§Ãññ2Ž`W¿–&¯f
-ªwK‚Ss¦Ã¤µuð)Ëñ–žô½d–æú8šQ5|¯?ùx"›f.àèV×úÕ ^qCÂþðlמh&-ÂS4Ú‡ÝÉѼ™ã>süd<쳚śéæÛÇàë{2“éK"ŒG•ª[ɶСo/GÐj+
-íï)XF².Ò}š+Âë¸ÿû‡î`ÏÙÐÊ#"”æ×u9@×%½ëWkÙ>PÎÖj "ê=QÙ4éÂ:ö` $¢QêÂX0Z½s¿å¢øø$"]9ðèUÐýÉ܈ñ¼¼²12æ-gˆ&™Ä"–™9
-\uÝ™HŒÁD'p.$¾EªØ[ûuF
-Ʋ@»|…Ú>œ ¦Â·@‰uã·ÄìLã?ñ®AzBÿ˜v“ Qí_’ܽþ`B^Ðà-)­‹ýi]
-æ»úܫմMøJ(ëº(!ç7ã6Zø©…TâÔœs‚÷9µ†Ì·Dä@KD
-B@ɱZ9™†O%IŽÖBÎgµJöâk\,»¨Â#JT>ÚxÒ§d[o&“)«Ê³9·Œ’ø›ÊÎ"d© I;ç$z2°ƒv<«Oæc`q;N±ÛâÍÁWÕo%Œp£š&a¨“Jíùp8vßÇß>*,«Õ†;ø×MÑzh|zŒ½™|[Oÿ;].˜,ÓB}Æw¨¯…¬‰ü¬bghà‰Ý;ûÇ\×ÑCf\lÚBMÝ D)ÊÖ'ó{ã
-®bw<ì´§­ö?ý±GPí·š}.c9b<'Ãï¯ý ÛP‰û¤ô+£ü?D³ÃúŽº Áá”OxÀ±v ¹‡£ÂM`ÝéÇë‡!qç»cÊ‹Òú]ÍA÷ûÏIêàÛ=­k»´Ýu+ÔãÍ%޵êb*P¯å
-ÆÑ%"üáE:mÊÐlƒ©NF4NÛbõäL»LpÝú¨ÓgV|‡± ÇÝ` Ä-2¶ÌÍ™–´U=I„ä{=â-×D± J·ô£v=~ßü®A{ ÀõfIö…„?”À„.2¸åöH»Îð£ïµa
-‘õ÷xõò*D’ç‘õÛJ$%Êbzû6ŽÑg"åÄ©:‘'‡Ð¹Ê—º{ü²£”òJ>{—ý¹ÛJ½Ô†øZKë­Øxî—CÑñxg»S\íï&;ùÆÖµPÞ©WÕñÃX¹«Ý^Ô¶‹Û]i­˜èX”•Ód9µvøZYÖpµ J«°s5jMÆãÍÉ YoŠiõ\†Õ³I¾6½’Ÿ†_«boU˜-°ãGq²°óÉzdÏKåKHOòu5ÿ»ù Ö¿áëÛŠéÃøñðᔎ´ž{Êl4Ÿ*Ò§•£V(ê@k!Í~Ô£t¤[‘øx"EÇt¤'Òƒº$o¬YHCQ í$¶~˜b ͼÇÛ±Û*©šxHnÉoô‘.ÕžÔPtùrôÝ¢U¬•öH³Ë+ƒqb›ôöI¬½[Hñ-¼&ÚzdkUÚ¾ "­7ä &y廋ŒÖb§jŸÓkXÉ;-„6ážÕø­rÿ-%
-âéRí-·rö#Ó†¢bíñ±Ækv9ú58,³¶ÅúúËi],ÆúñÜ-FŠshlž.¯ïêHoSqwÔm¼Õ‡¯š éÝ–ØÊ¥$„tÍ4,5úÃìY;%ÚÜȹ~[÷wmÒìrî«W{b!­ˆ‡kŒ­1ÇX›¿{Ÿã£3*Òó͘ÂDzÐ?WDR$ùÕû”xþœX¢u²tÐèÝß%âT¤W±ÁéùûéK# EÝc½¯‹W£-:Ò–½¬ímmÓ‘Žö—hHA&#´WÏõ¥)ƒÀ÷ÇâõîA…Žôp§úütúøHEúxüÕÄH‘~qõó6Ó«1>äÅÇÉwŠŽôèsôs\È+¤€£}n¦L£çÉéí¥XýøÙ§"Í¥–"{)c€vã×É4ϹgiGI8˜&q×j¯a¤rl'Þ°´%¾¬mÒu )`Ahìç¯!ô·ÇN¤“áê¶Žtº›tŒ4òоOhHK·RÓ.×Ç“Ë`´‚[*5Sx¬€´<u‰ÂÆRVCº+¤‚p}¤išFYÙ(`¤‹Žve<nw©è@:ûCcýîGH'™Ï ]Óìnœ
-ò. û/!Ý~è·Ÿ³öN5.WŸ†Ì··§ÒÏëí»Øx‰þYo]’Doe•ñ5ÌÁj²lô볟s¼Íæ¥ç ýíä+ïâÊìà}é†ö^Š'ÍæÛ¼¼vöÂ~ûÞ~Š™s¿/Ê«w]æÛVr°+³ßvŽ_7­·Še——ºãë|cµ±u9ÑÞ¾Æ~ Žo/“†qú*-m¸(vÙÙ?ÐÞkR®’ü3ß^G;éûíCecÛ åýKô)·Â|û9=5˜o¿®äÒ©õÖE±Ÿ¯ÚÎëkèÒéf†ùv_VwnØ‹vóëëÕÈjóaù¶Z<ìô™o÷åÝ%‰M±bD^Il0Þfbu{ÍóF|Óñ6yq:ÙÕß–…-'W6.^êkEë½:Q×ÏìXYìÅî˺üy‰~£·#Ý­=g4ÑSNŽ´_69&OW‡Yޤö ·àa~^ ô¬Y¯œ•Ñ?ר3½7MFèøÚg%Cò—äØöIJ—çàçØì±e%îÿ`Þ@žÁéÃü ~ì͈֥UÀ÷ºeâ[Nlw –ªã¿!e·ã¥PÔB‹=Òì2òsîéHÕÛ;&RP"Ÿ’Ã#ÇŠ=&R¤òº,¤=©z>26T:'öVW—-¤Øú7‘*ò"ëßiýÛ†4q‹½W­ÀÛ2)¶þHÁëÿÉB
-c±õ‘‰<QÙH‘õÏDŠ"ûÿ>Ö­ˆà…´c"Å6……ñ¾ -²).l³Ú/èñ/}"å»ÞO»§¿ŸÉûŒ–Ùåß§êͱo»Ì»¾îtiQ‚1?uiébÝ—ø¢Î Ù©ýuá²z¾çàøôÇòƺõÏÎ(Þ»Ðu$“4g”Ø™ãÄN¡±ò‰{±S¨ßW@pµ«³b‰&ýN5ªÿ³~8Ô`Ø@`Ú–ÐÜöHkäˆ>Ø+¥ßû•¨ùÏi1ë1³c³qa©“Ã}ÙßÕcJÐåËx°Š Ú¿5ƒ:šÝ®‹cb'«vš7è°¸Ÿ‰Fñ?hA^Û½$Z§¾
-MG§È.=ÿÅ`é®Ë±]‘ˆ£9˜ä -ÿJ~DGÿèלyÊøbæøBQk„øæ ów¾ä?ËæøÖô5F!2^/=ˆÅ?C¼>5Ï‚“XÀ¤µÒg *Ä³Ü bm¦­,k]Ù4²¶²ê¿Á)O¥;7wúJž›òré®°ïM÷›XvÑ“p‹ž§ª]ô(LÑò[ºÕ‡æ˜$ ÙeW5ÑC§Ýª"b˜ÑŸõêºöN;i@§Ým*ÂÛ,®Äñ8êÐn—‚ÔbxpÊîÕÅ¡©ë«únµ#•¤cT¤#FÕ?VõÙw‰Ñ*`¹MÂÀÚw­É†ä:I¬Bçn*ŒiZIí•X÷A‹óÏH‘­¥ß‡Émcå+uèÀ$^`4P˜îÄ.Ïš›ïÚ5^¾óæ:Ð•í¥›?Ϲ\–Ö/¥uôÏ}’ؤp- Œñêm:bä„¢`B­@´{mÀøL)è^ǧf—ˆ~á±LëÔžíÔ;Ö ÷Äþô2í²ÂÜSby|‡I÷”ôê~V¯èùÊOBQ¦bâ°­Æ`ÍÜO™j) 2¿uD“Fpë‰Æû½º]NSˆu8´¯G—¦»ûL]y|¦÷‡Ç¤ƒ.± :cêBQ¾/ßÓ°ð³ùm38ˆzæ¯~òcÒVòÀÎýBUwx€ÙJÐ~;¼:°[o'&È I«nnŠ=H1»D د‘=ó’»×éÎdFëØ¶ÿýiМA–AKUÐréæ=â#ǛΕÓÝ¥…qeéæw%˜£¬íǺf²¶LZm'œ:·K«¼Î‡i[:©³31Õ²on6BÊ/þÓ´3ñvñÑW²»+>R€«#Ûr6šø°=ÑÍGN2TÔ[…®ïøäÚ¦¤ý‘y¶G~œt"  ¿šhÍW `5ÀŒxØ0TñÁ`¦·ÙŠéÔòŒÀ.-Ë=N£Þj™W
-ûA</©"¸—°-=ê¸ï"EÏ8‘óÎ:˜´˜|8„egê¼óá‚ß?6K>íôÉÏ¢óáæÈ³çuBuqùp(j='räÃQne&qÍžg; e|[t>œóÞQ-#nÑùp¾·,$ζcÅqÔr¶|8§/ÆÚÖA™lógÖ#·°3‘
-ÝÍ7WõÛO•Ï(W™;߈""ÌÜeîtÆ»ÐÝÜeî´Ü7ŸBw|›G£ƒÜs¥ì^JÞ“ÈŸgq°°#J£Ëäž9—†¶à]ŸÌ]T Î÷ì¡ßúDitÈyöŒÀs%Òñœhùg²qpçc‡‘!ê0Cö•ÌWa 0/ÇœùDèÒTæ˜iwC±ö{ê'?3&vÙNCÁ¢ò9Î}
-@ùžã> ÀøNt{lƲo!™óo… Š‚×ë³Ï ‡«¶+
-q²ë|ˆ¡¸2Ù©™Âþ¹ìWb-«„3±ö|àN¬=,îV@l!…ŒñƒÞò3Rw1IyA#¥o½W¯3Ôkî-]”‰ç>Aí鉳ÎP÷'_ ÉL1o>nI¸AµþUÁ^œ°·ˆ¹yÿ2P¡jÖî*¼6·9¡Añ:Õ
-ñ­'ǦWÐñ™Qk”w¸Ê"£K®SZN~á&z SZ¡¨W§Øqâ`]iÉ>§¥÷Çu6Ö!®ª;köÍ못fÊl®Ànr\}íƒ}ª.êòÆÛT„ï†CŽl$Ïð2ï.ÏSuž›h­œDוq3%»Ñ·¬ÝkýT1²l¿EeÎ{ -í®8f¾˜Ÿ×â¾+ÎâÇÇì‡F([¬íZ zl S[˜Ü®9%̬»ÞZ‹ñŽ•ù:[Ïœq~ÿ®ÇÇŒª¨¿®_ùqp{„Qû)¶}ÃÞ –Hæªg1GY6ïL¦@9V…@÷]rä¿ôê^±c_kÜÖ%⨾¾[MpmÀTÀ¯ŽTNòž+T@¿’Æ>ógí¼÷êþ‰:Ü‹ÁQטZe&
-áa:ÏÁËäÍD›= Т§·Ü°çXÍäÍ4}䙲
-ÿJQ>¿Šl‹)ʧåŒx(óå E)Vá‹ò¹ë#ÿEùØõ‘Y”«~å<EùȨêT–Ù)D~©Áìª~óß µ¿ˆ»¡8ëúqÝ 5w]?bh ¸ŠU×/Ø9¥YëúyWõ›én(J]?ï¨Ý^×¾ø<¡®ŸÿJ^D]?ï“!fäjκ~~™\
-èzVõ Et™uý¼‡æˆ]Ì\×ÏÖWU¿*€PëúyˆvBu–º~ÔtD¯[Íù Ã)K½ z†º~Þ7™{âsÖõóTte¬ÅP×Ï;,è*º~Þ®.õô uýhi’ëÍWo9ïêúyCAqþEÔõóÞP qÙ'ñÝ™‘:k]?Š©ITõ#«3ˆsÔõs°¡h¯êg»³+pzŠhÖõóÍ{]H]?ïª~æJž³®Ÿ÷k"#u®º~Vþm-:¹®Ÿ7±»€º~¼6ùRToÍ
-w=>ŸrrÜõøæªëgB¡²OÐlW]?¼ßÓ¶ý uý¼-ytãÁ"êú±tø•{'q¶ü-sÞØIôcC¿º~ÞûÍöS³×õ³SÛé-ÎZ/Ø! v=¾°YÕoþz|<IL~·7¸Ïj+ÅçÌH¯®Ÿ-°íªê§e Í_×ÏL•òª+:w]?o3‡±Æ×õó®ê7÷­Mz]¿9c}œuý8ò^P×Ï»ª_àz|3eá:¤¥»®ßìÉðDU?Ë\uýÜ¡d²ªë–³ uý¼w9´ØÌuý¼:9bJ3×õ£Ì QÕÏû^8þº~³Ç-í žóÄð+ç¨ëg .ZU¿™O:êúy®¢È|uý¼ CÍ{¿®ŸwB¬®‘ç®ëg¤³ªŸËã¾ÉÊ^×mi6ŒÏMVœuý¸l˜¹ëú‘3éÞÀñÈ®eð'½®Ÿ·rðÌâ\XB¬¦÷Óõpçe£_ÒO|8ï•z×nTtèJxÊíz¼w¤-ÚV“±Æ¬Ý›í™¯Å¦tTq›††aÄôq?kÒóÈæ‰¶&(÷Mž¼G@­ìG’÷G+búæ+§5BùT‘•æ Æ‘t÷~¤*ã÷ýÚÎ÷cáôr-žúIÄJ¿%±ñvT\þý+e#íž¿^ö¢™üfcõðø÷,óûu{Šæ2‚ÚÍÖn„aÉ´êêKéìër·w~˜½~¿èe~¯âýוëbB­|.]œ|m|oÝ û»ñÁïsî7:Þd"×G»±%^ÏF_ï›ÍÄßûò½:|èoè¼s;w./ί"Bòi/"¿ý^%·”ØžX+”ÄÚkw_¬gWÏÆã—B|<É_7'ËOÙÎ$Ó¹?13-/’ÛéÔµ ´
-KFÚÛgz<y¢bs…e-·Ú-Clù¥›w­çB±{:BµYÕ“ü{‘¢kŽÖ>X˜0Üé*še%Â+ÎhŒ·cý“å«»‹•Á8][•Õ·¿åï^¤‡2I÷äÐÈßúH=BçÕ8'1R¬]\DÅ•~ûû'C»É>r° í¤L$ÍYñVbh ÖhtØÉFË¡hå®Ö¿Á4Ëõ³›ìQ¹·´—žníï¥'½ÍZaùë¤z½§<Ù;õï«›‡b#é
-Íïq8@¡èÜ.ÍBÚ<cÄÛ†ÅÒ«hâÆ‡‡}Í÷×´)‰mŸ¯éŒ+¥K¤á$bÊîuµ;$AÑÚhÄñÄ#•Žv”†Íw€åJê>‰Íä§^;˜ÛP´òFUý ¡æ£ïØdš"Š~žbO…ÜgA#ûI{ñø†Nå <Œ¸T}ÚØ2žíaŽG»g¿ðgM0eÍ#Œ´óUú^Ô°¾Ân²”vŽ%³Ñ“¶X4ÚÖ·× ÷ê(‰Í3ËïøßP.W„L8¯âÿIŸý}÷ÇÇã·Ax=´J›’t9è kã~ÿ¢ÿ?Óʰû÷ÓLÃátñ¼Ülæ3•~wØë‡ñö\æ%G\² õ@ßy$ƒ´¶-ImuV^ õ¯ÆòÙv»ò*Þî–ØI(íH*; EQät+íK‘õ÷ÏsôgM3µp-5JøÓš][®ôÇ¥¿jò°uíà*ì_d¾;Õ_p¢3( ÐÈl ;êÞïK/Gòyî`owþ즰~Ð#t¶x8Ç¥„}Áš®F[G*Æê59‘•J>YOìí¡§û‘äéÒQ$َЋÝHª¨ô"ë‡7ÈÚï2ÿöoÞbtˆ1©{éeiS_<µgSôŸ ñziQPéo;ØÒõò×Ñצ¿žÆ"–‰ë¿>ûH7:¯Ä~Ñ¥è¤þçF<¥óŠÆ¶`è ÀÜ›ÎS´V/0´`¬ò\ÂzAŽ`g;I¼h¯”·ep=V(Ý]ië…²²ùV4^8ø)t` 뉹^^'›O$îzS@‚w ø!‰yàÄÏ?xq&á?•ÝËüy²gÁ~Ö'5ÌÏk`CöKxµ¡ Š<6rZyPóÇ0µ'Çi$ÀÖÁï
-üy‰Á®i““>¹WÒ‡ç_HG]$ ¥yÀ·­”‰ôÅÀ‚WüP¬’no­n¼ b—µ­ªúIÄ•µ¨³&¬L)fˆ2s›¤
-H¶) Ä÷ó²¾¼nÛª9ô6¹¼:Ç)¬t£ªs™Ö—}çF”:­f~ÝKºZé<É;…¦ sÕi£m ô›7<Cp%'Û#ÞÞÒäØ>úgWãýõßÑ1íM¹¢³=¿vD¼?“~ ¤CÑõc íŠÎ¨iGû¥Ä8KÛ$÷3Î#6N3öu°’InŸW{ÈÈaD½Æã­ƒë¤6+_tT[Ø,ÓXþÍþ
-‹ÎÒ’$='Â1 ¡¨}¬1+JŠ#™&ˆGD÷ø5“1íæ={´kiÙ½p‚h/Õ“Áû@fˆ‘S;Ó0´ b(¤Äã˜_i
-ˆGÇÚ'In§Øƒ³%…¶4ˆÖè=CÝñPÔ«<ƒŒ[KNlTÎ;&ªýêãäa[ôN]”Ì)¹}4\Æi]ƒ˜·Ýršä`Ãèjôß4ÉM÷ö_5ɱãYNýË&9aóÿ‹&¹vJþ_6ÉѼ0Lèšä¤„ù÷Lr2øï™ähQnšä%kÊ4NÕ`ðɵÁ®Õ8°½´™9i46ƒõ" 3)ò‡ z›&
-Ä%!“s…l"œ>ŸŽ?oáx©Tì œ §mÔÔA‚¿¨wW›’Í R!—g¬ ´)²Ïçsa%?²…l8#åq#EÉèMôÝ"儌œ)XmDÅ Æ|¢ã‚¯ÌGÙ¼ +j!lÁÉË\úøÊìÑÆì² Æ9®.QÔœ˜ÉçÃä̲b=ÑP¨M^U$ÊL.èL^ƒªTL-ý‰¢Yɱ$!¯ÀbÊÈ€9'+xJ^™O¹òB¾@63BFUUùDG†Èe<Êf¨‘'/
-°tó2ã ¢—Ñ%³•ÑkŽc`˜\®Å’É
-ª3™Q³@¯|_R…LAR¬g-âYFr-bë[Ú3ëÛ×Ð%}¹gQ(ºßþÇÿûÑ›¾kKÛzøÞÿx{ŸjOaUÿG{‹Òxòö$Í+0«b^§›ƒi8>ùþèömR£Ž'Â7×À6R^r¥V³¢PÈ©hàÖ3Uä¬9)[€¥’A•óÐ
-~H@øze>é†$E$)#­¤‚’ùÄÀß™Ïr /2°d,HZe²>ã |göÊleöÜ„äßbØEÊCò ÃÍKbÓÍx¦ª‚ÓtË ªœÍ‡a:
-ӕͨèk5'¨
-(\ê3ãÛÞ‚ÔÐüÌ |à`n`$sg
-ù|ƒ¹e (Èžœ¡*Ð"µžÊ ô³
- æÅ‚¤é8Ÿñ¾3{e¶2{nBro1Ì-çà‹\ÎPÙôG†“39Acé94ŠLÄ¡ eYļJ4’D!§(„2´žØà3óÖb*|g
-´ d!œéP=£d0«~Œ°„
-™¬.’j1}VA5™?Ð=$ƒéµF¢jƒ"ª$äì
-Œ— [
-ª¬†-@ÀÌ2¨ ›þ
-Ùè®°Œ}Só"MVs`­F²¢9¹ 󉑯xVÈ®° ô²á
-kèÌz
-çt×U”-WX¦€!mº½yÍí¥=3¿mQà-Œ£ VÊŠ°h2ØŽ…•Ft:L~ .9pzñ“ hµyä”àϲr{@²)ȓʨ!ŸË„S šDäþªÐ{ð Ú“\䲨b$¿õ•ÃÎ"¿É€¬=
-,f¹žj¨(ƒs€žH9Ì%A„ŽiakLÞlN;‚œ×¢Õš<Ô€I2¿AýËesH®˜€ed¡ bäè%~’ÏfÂîq-ŠºNƯ–6¸D(.“Š$»
-¢ÄR ŽsHÓ©2ŠºÃ¼g*È‘nÁŠ„EZ=, Ò›n`lŽ
-ÔmÜ#Ð&® —½Gj!»ÏId·Q‡2ˆmZnXì>ʰijRA]üÂE DF/°)…ŒŒCS°IÁc’P@IA<Š u˜d¤p´ÏÀCÊ0‹IqX4X9aP…À¤ˆúà¢1§?É¡'0fd+ùÂŒ6P,èø è½â;ÜMù†:t¨$"Õ‚z êÍ¥°{pÿÖê•P”LA&Òw6K€½$$òÐ €¶žÀ@±…g}Že6#áaŒ½ íSåT4¾¨\4ø H? …ñaaiŸ©
-¦"xÊ…Œ¢W@?jOTEï
-ü•É`;MÎg%=ül‡· ¡uJ•,d?2W§ô¾‹ö¾ã>a!á· )Ñ*iÛæÕAïn§Ð)÷¦¢m£—ÇÃÑ$ô7é{€#œF/Côô°=þš„¿Ãÿƒá4üÿY;ߨ`? Y>WÖðK³†7[A
-;Úñû3@6™Žqߘ¡nîè{Þ(ÚæÚõN¡ýŸP
-ÌsOSheÀÿ(Yüà’ð&àè½=ú¥}‘µO²”Oò¢ñMžø&/_á_ŒïŒ¯¬oRÆ'îÞY¿þÿðÇ«605ÚDD£'í·þŸýñ݇Þ&íÿôÃíÁ
-0000000016 00000 n
-0000039997 00000 n
-0000000004 00000 f
-0000000006 00000 f
-0000041195 00000 n
-0000000007 00000 f
-0000000008 00000 f
-0000000009 00000 f
-0000000010 00000 f
-0000000011 00000 f
-0000000012 00000 f
-0000000013 00000 f
-0000000017 00000 f
-0000040048 00000 n
-0000041054 00000 n
-0000041085 00000 n
-0000000018 00000 f
-0000000019 00000 f
-0000000023 00000 f
-0000040119 00000 n
-0000040938 00000 n
-0000040969 00000 n
-0000000024 00000 f
-0000000025 00000 f
-0000000026 00000 f
-0000000027 00000 f
-0000000028 00000 f
-0000000029 00000 f
-0000000030 00000 f
-0000000031 00000 f
-0000000032 00000 f
-0000000033 00000 f
-0000000034 00000 f
-0000000035 00000 f
-0000000036 00000 f
-0000000037 00000 f
-0000000041 00000 f
-0000040190 00000 n
-0000040822 00000 n
-0000040853 00000 n
-0000000042 00000 f
-0000000043 00000 f
-0000000044 00000 f
-0000000045 00000 f
-0000000046 00000 f
-0000000047 00000 f
-0000000048 00000 f
-0000000049 00000 f
-0000000050 00000 f
-0000000051 00000 f
-0000000052 00000 f
-0000000053 00000 f
-0000000054 00000 f
-0000000055 00000 f
-0000000059 00000 f
-0000040261 00000 n
-0000040706 00000 n
-0000040737 00000 n
-0000000060 00000 f
-0000000061 00000 f
-0000000062 00000 f
-0000000063 00000 f
-0000000064 00000 f
-0000000065 00000 f
-0000000066 00000 f
-0000000067 00000 f
-0000000068 00000 f
-0000000069 00000 f
-0000000070 00000 f
-0000000071 00000 f
-0000000072 00000 f
-0000000073 00000 f
-0000000074 00000 f
-0000000075 00000 f
-0000000079 00001 f
-0000040332 00000 n
-0000040590 00000 n
-0000040621 00000 n
-0000000080 00000 f
-0000000081 00000 f
-0000000082 00001 f
-0000000083 00000 f
-0000000084 00000 f
-0000000085 00000 f
-0000000092 00000 f
-0000044323 00000 n
-0000044397 00000 n
-0000044593 00000 n
-0000045557 00000 n
-0000060869 00000 n
-0000126457 00000 n
-0000000000 00001 f
-0000041170 00000 n
-0000040403 00000 n
-0000040474 00000 n
-0000040505 00000 n
-0000043646 00000 n
-0000041556 00000 n
-0000133401 00000 n
-0000043759 00000 n
-0000043809 00000 n
-0000042654 00000 n
-0000000219 00000 n
-trailer <</Size 104/Root 1 0 R/Info 99 0 R/ID[<088B91DE986C40C384A339FF4EA2AB20><65769AC03F314FDAAEA9D1F1344EEF4B>]>> startxref 133575 %%EOF \ No newline at end of file
diff --git a/images/Android.ai b/images/Android.ai
deleted file mode 100644
index 1710ccae7..000000000
--- a/images/Android.ai
+++ /dev/null
@@ -1,3156 +0,0 @@
-%PDF-1.5 %âãÏÓ
-1 0 obj <</Metadata 838 0 R/Pages 2 0 R/OCProperties<</D<</RBGroups[]/ON[13 0 R 17 0 R 33 0 R 37 0 R 61 0 R 64 0 R 83 0 R 86 0 R 112 0 R 115 0 R 218 0 R 221 0 R 325 0 R 328 0 R 462 0 R 465 0 R 609 0 R 612 0 R 729 0 R 732 0 R]/Order 728 0 R>>/OCGs[13 0 R 17 0 R 33 0 R 37 0 R 61 0 R 64 0 R 83 0 R 86 0 R 112 0 R 115 0 R 218 0 R 221 0 R 325 0 R 328 0 R 462 0 R 465 0 R 609 0 R 612 0 R 729 0 R 732 0 R]>>/Type/Catalog>> endobj 838 0 obj <</Subtype/XML/Length 42281/Type/Metadata>>stream
-<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
-<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.1-c036 46.277092, Fri Feb 23 2007 14:16:18 ">
- <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
- <rdf:Description rdf:about=""
- xmlns:dc="http://purl.org/dc/elements/1.1/">
- <dc:format>application/pdf</dc:format>
- <dc:title>
- <rdf:Alt>
- <rdf:li xml:lang="x-default">Basic RGB</rdf:li>
- </rdf:Alt>
- </dc:title>
- </rdf:Description>
- <rdf:Description rdf:about=""
- xmlns:xap="http://ns.adobe.com/xap/1.0/"
- xmlns:xapGImg="http://ns.adobe.com/xap/1.0/g/img/">
- <xap:CreatorTool>Adobe Illustrator CS3</xap:CreatorTool>
- <xap:CreateDate>2008-05-23T23:33:16-07:00</xap:CreateDate>
- <xap:ModifyDate>2008-06-01T01:35:11-07:00</xap:ModifyDate>
- <xap:MetadataDate>2008-06-01T01:35:11-07:00</xap:MetadataDate>
- <xap:Thumbnails>
- <rdf:Alt>
- <rdf:li rdf:parseType="Resource">
- <xapGImg:width>256</xapGImg:width>
- <xapGImg:height>164</xapGImg:height>
- <xapGImg:format>JPEG</xapGImg:format>
- <xapGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA&#xA;AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK&#xA;DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f&#xA;Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgApAEAAwER&#xA;AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA&#xA;AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB&#xA;UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE&#xA;1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ&#xA;qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy&#xA;obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp&#xA;0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo&#xA;+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq03XIlVuKHYq&#xA;7ArsKuxV2KuxV2KtjriFQo1azIDKJWU7qywTMpHiCEoRkkuOrWY/Zn/6R5/+aMVaOs2Q7T/9I8//&#xA;ADRiq063YD/f3/SPP/zRirX6e04f7+/6R5/+aMaVF2t1BdRerCxZKkGoKkEdirAMPpGKrp5oYIXm&#xA;mcRxRgs8jGgAHffIzmIgkmgFYP8A8rLhtoxAsDXzxkr9ZLekJFB+F6cWIJHXbrnNf6IRAcNcZHXl&#xA;fnya/ERFj+YNpqF3awSV05C/KZ2YMrUHwoGoKBm6kjp88tw9uQyzjE/u99/1KJ2zPOibHYq7FXYq&#xA;7FXYq7FXYq7FXYq7FXYq7FWm65EqtxQtlNENem1fvwJCFiuGt0430qUMgjhn+yHDmkYcdFep4+DG&#xA;lKV4g0qM2wK6owql9zqqiZrazi+s3MZT1qkpFGrVJ5ycWHIKK8Fq261AU8saWklsmuofNMHOZp5b&#xA;mGSO6NWSKifvFKQqeAKt8IZqtx2LHJGOySGVZFi2OuIVIdOvaaZaCvSGP/iAyykqjX3vjSqTX3vh&#xA;pVFr33xpVJr33xpUx0G7hjs724nkWOJJ6vI5AUARR9ScryTEQTI0AqR+fr17/T7KLTpo5rWZ3aZk&#xA;kQAmPiFG5Fd2Oc523mOXHEYyDE3e46U1zNsMuLTUrgRB44h6MYiXg0K1VamrUIqd+pzncmLJKrA2&#xA;FfwtdOWz1FbSS2EUJSR1cuWiLgqCKBq1A3xGLIImNCif6N/Naei+VtYjg0G1TVbiOCZWaGIySL8a&#xA;pSlDXsCBnW9m6sRwRGWQB5CyN22J23ZLm5ZuxV2KuxV2KuxV2KuxV2KuxV2KuxVpuuRKrcUKF63C&#xA;2dvDj/xIYso80CZ45YnilVZIpFKyI4DKysKEEHYg5JsQEeu3xMs9tam800IotuDqs8jhqMyeqyI0&#xA;RU1Ds4JoSOSspxpjSm2q3d1dRQ3Yk0yGX4oYg6mSb92ecUkiFljdDVuMbVIAZXoHUGlRKyQW1ulv&#xA;bRrDbxKEiijAVFUbAKo2AwskHo0gl80b7lbWVh/yMjH8cZcmssryti2OuIVgljeUsLYV6RJ/xEZd&#xA;SVzXvvhpVJr33xpVJrz3xpKk1574aVF3D8/Iert43Ef64M03bn+LT+H+6DCfJhkjf7i7dfCec1+a&#xA;Rf0zh5H91H+tL7otPRC5Sh2Koq4ctZ2g/lDj/hyf45dkNwj8fvS9q04U0+1HhDH/AMRGejaf+7j7&#xA;h9zeERlqUs1nzNoGi8f0rfxWhZS6iRqHivVqDemKpf5b8+aH5osYrzy9ILyCdTJA8hEBMatx9Ron&#xA;/wBIRW/ZLRb1B6GuRlKlR91falAYndIkjaRVlVQ8gVOQ5u0v7sLQHup6dcgMoPcpTTLVdirsVdir&#xA;sVdirsVabrkSq3FCD1h+GnSt0px/4kMQkc2JG4W9HBj/AKD+0v8Av72P/Ff/ABP/AFftWU2Wjvrg&#xA;p1xpChcvDPE0UvxI1DTcEEGqkEEEFSKgjcHphTak1yVj4s/Nh+1sCR702r8sKFnlWfn5tZa/8eUx&#xA;/wCSsOM/pYlnWUsWx1xCvKLS7pZwCv8AutP+IjMgBkua798NKpNd++NKptd++NKptdHxwqyXTbS6&#xA;1DyHqcFshlne4BVB1PD0mNPoXNT2vhlkwSjEXLb7wWEhsxfU9NvbDTLKO8iMMkks8io2zcaRLuO2&#xA;6nOJ1OnnixRExRJkf9y1EUEqzCYuxVOk0LVb7S7Gazt3nSskbcBWjB6/F4D4s2I0WXLihKEeLmPt&#xA;ZUaeu2cbxWkET05pGqtTpUKAc7zFExgAeYAbwq5YrGPN/kzy/wCY7myGsQNNHwmtk4OyMPVUOd1I&#xA;24wkfTgJVi1zZfmRp3mdrTyjpWmad5ftn5u08e12jKnIBkcOjbni3iN1YZjzmK3ZBmcbanLpFyNa&#xA;a3tZZvUQekSUjjccUDM5HJt9yKDNZlyUdmQCb2dwLmzguQOInjSQLWtOahqV+nN2DYtrVsKuxV2K&#xA;uxV2KuxVpuuRKrcUKdzbw3NvJbzoJIZlKSIehVhQjFUmn8nabJIrxTT26gUMcbhlPuTIsjfjkhMp&#xA;tByeTLv1WMWpUh/3XG8PJh83DqD/AMDh402l8nlfzTHHI/8Ao8pWpSOOVuTDtTmiKD82yXGFtKr/&#xA;AEzzLHa87jTrhKkBTBwnkVux4wmU7fKnjtkgQVtF/l9p2vtrs+oahZtaQQW8lqWlVozK8jxSK8Ub&#xA;jlw4oeXLo2w5dcGQiqQXodQOuw7nKUJPovnLytrSCXS9UtrpDL6ChZAGaTiW4BW4kminp4HwOGkp&#xA;Ify64nhFqJjiG0aPByYLTYFhIoJA70yzjVaPy5lYAjVVIO4Ig/6+48auP5azf9XQf9I5/wCquHxF&#xA;aP5Zy/8AV0H/AEj/APX3HxFW/wDKsZf+roP+kf8A6+4+IrKfL+iRaNpws45DMxYySSsKcmb23oKA&#xA;DIE2rta8vaZrCxC9QsYSSjqeLCvUV8MwtXoMWorjHJBiC808taPYah5jewuKm2Hq8QrUPwdN847s&#xA;/SY8uoOOX07/AGNMRZb0zRbG485PpMgb6ms9xGADRuMQcrv/ALEYdPpIT1hxH6OKQ+V/qUDenqWm&#xA;aZZ6ZZpaWicIUqQCakkmpJJztdPp4YYCEOTcBSKy9LsVUbu29dFCuYpEYOkqgEqehoDUbqSNx3wE&#xA;Wql+jQ39/cTzU+z8fpU8f7kRV+muQ8KKbXw6dYQyCWO3jWUf7t4gyVIoSXPxEnuSckIAcghEZJXY&#xA;q7FXYqkfmGy803QhbQ9TjsHgk5TRzW4lWdQ8bemSxqoKq68l/m9sVQPlrUfO1tpc1x56h0y3uTdc&#xA;YBpbTGNbZkXiX9arM4kqDxptvQdMpz5hjFnlaCUzPmrQKNwuAzKCQvBxU+ALKBvmN/KeDpL70cQT&#xA;WP4o1ZlAZgCQDUAkdj3zOibDJguk6/rk/mHzjFcpN9S0q/sodLEpjijo8CGUo4ROUdX35M5rUVGw&#xA;BVnfEYKV3EY0ruIxpXcRjSu4jGlWTrN6MnoFRPxPpF6lOdPh5U3pXrjSpF+i9PlYw6prM11dNUPG&#xA;tybRQT1VYrdo9u1GLHxJxpWP6x5B8q6Xqtl5iUp+lbBRHpn1mCK59MKXIEQAhlFDKx/vKb+OUajU&#xA;wwxuSCaXw+fPMFlS2vtLjuWiJV5o52hlNPGGSNgDT/i3NbDteMfTISsMeNPLHX9b1SIzWOlRJHXi&#xA;sl1cqtCOpKxJM21em2bPBnGUcUeTIG2P+b9bm0bUNAsNU1NZrnW7wQG0juX0uKK3RS806PGk80hj&#xA;FPheVVbxXL0pxotpouqW8s2lak8dxBLLF9Ysrx5wAjkKXSRponJWh+NTirKIVkWFFkf1JFUB5Kce&#xA;TAbmg6VxVdiqx54U+3Iq0pWpHc8R+O2AkDmqT6f5f0CxvptVtj+8csrHnyRGZqMFA6Gu1MwMXZ+H&#xA;DkOUbE/pYiIG6HurHyfomspq99eQ2F3du4g+szpEryuKP6YcryY8unvhh2bijmOUD1fr5rwi7ZHm&#xA;eydirsVdirsVdirsVdirsVdiqHnvbS1ieW4lWOMPxLEnqe1PHK8uWOMXI0FJYb5ku5rnViQYZrWJ&#xA;OMCNIoUh0rzpyU13qPozne0Mpnl6GIG246jnza5HdJooHjcOwhkArVGlSh29mBzXRgQb9J+I/WxZ&#xA;T5U1eO3sJYb6dEihZRCzODs9Tx2J6cc3fZmqEIETIAHLfvZxLHvLUNpJ5u/MBrQO8j6tp31luSzK&#xA;HWyhbmvOKNUX0yBTk5rvUVpm8ZvS8VdirsVdirsVSvW5rCQR2M/rTSSHn9Ttq85EFRSQrTjGT15M&#xA;oPQmlRiqR+YNQg07RnEWhPbozLElYrWRFPU/u45JOw/lzC1+c48dxNSRI7MLvLzQrySBQ5srpIwP&#xA;St3NpuSW5G3ZQh2I/YzQajUTnXGLoNZLvqd9yrFqnMndjeQBvxhMdfuzFuB/H/SSE40K7eC9uDq2&#xA;sCC3uF5G2sAsJkbkAFWNPUnGxP2CpzcdmZanImhE+Y5/YziUtuJ9Pl/Nb1rPRY1/wpost4lyzoly&#xA;tzqLGNuZYyKS8EI4cyH3NfhzfM2eaDaWckFlDeWMkGp2kYkWWRFVhuC3CeD92VJO6BunUYqyLFXY&#xA;q8l8y+Q/LsU8r2N5OItRS6gvBBNFGVWa/wDr8ixuEqreq1FPYe5JzUa/W8NCNEXvv3dGEilvlDy7&#xA;D5Yjuls7iaQ3M7XQd5UqshChf9iOPTNLLUylIS5EDoWNpv8AmBe3WpX3kMxR6c1w+pxNM97KqvCy&#xA;yxlJYI/rFs8hLx/YXlXb5N0+k1HiQBP1Vu2AvVcykuxV2KuxV2KuxV2KuxV2KuxVjPnUsdITkKUu&#xA;gAKg7cH8M1HbP90P636CwnyYddV9Va/77j/5NrnO5OfwH3BgpZWhVUD6rIe4dBX6HywfSfeP0pRP&#xA;lZZjq/niBlt0txf6a0SxrAznlaQcjItsFl5FloPVqdvDO1w/QPcG4PThliuxV2KuxV2KoBrjU5Zp&#xA;Ba2yRRoeH1i4YgtxJFUjUElfAsw9tt8VY/5ttPNFzFaxw2kV3GrsZDDIUappx+Bxx8f281XamCeU&#xA;REQxkLYPeahZSySJcW8kcRY0SaIugUdKsnqR9P8AKznZj1ExLWg6eVwPh+rD/IjKg/8AALvX6Mf3&#xA;nmqLtFIhWLSrBYxcP/eSL6CsR8INKGRt2PVd/HJ8JIAJ5n3qjPKp1a8fzXeQTRzvda5Ho8Syxtcw&#xA;lNMiii5QkMnpIjLISGDfvAT+1nZQjwxA7m56taSXLxf6RCIZVPEqrB1NO6tRTT5gH2ySq2KuxV5T&#xA;IrC0jqKfvJBQjuAlc4aQ9A95/Q0qOVoYx5zVF81+SJJUmmEWoQzpbwW8U7SPFNFIgBklhKEcNitf&#xA;keh3vZI9Z/qs4PoPOgbHYq7FXYq7FXYq7FXYq7FXYqgdU0m31O2NvOWVQ4kVkoCCBTwPY5j6rTRz&#xA;R4ZIIthfmLQ7qzuZJljP1FQiRykg7BQor3rt4Zzev0csciQPRtv8GuQSuayuoYIp5YysM9TE9R8V&#xA;OuYc8MoxEiNpckUyPRPKMk9tN+kVaAMyNDxK8iAG5fzCh5DNto+yzKJ8TblX2shFKtFhv7fXPO8d&#xA;1dO1v+ktPjsjM88Yjtxbwt6cZdEU/EW/u2IPfetehjEAUGx6QOmFXYq7FXYqsmMoiYwqrS0+BWJV&#xA;SfcgN+rFUILLUGXlLqMiyHqsMcKxj/VEiSt97Yq76vqsVRHcx3Cf77nj4sf9nHRf+SeKsB1KxdfM&#xA;C6bBZSJy4iQxSJMqlhyJXmYWNF7UzltRo4fmPDga/H6mojdCJY6jc6lNYWFpJNLEWHOQxxJ8Boa/&#xA;ExG/gDlEdEZZDCJsj9C0nV95ck0rRX1zVNQFsNJtpbqaKFf3f7kNN8chEjkDvwQE9hm6w9lxjwkn&#xA;eP67ZiKE8jeXprXSPLVvBdRm8W1fVL1o4CtsZrxjISsQWNV5O7dOLbdBXNsyekLy4jlTlTenSuKu&#xA;xV2KpH5p0eC7sWuAH9e2VmiWPoSxBNRQ1zW9paSOSHFvceVMZBjC6DVdJPCal81Ljb7I5fs7bfBv&#xA;vmlGi/u9j6+fz/VuwpC/mPpMdtqfkdIdJ1LUbez1NHkvNP8AUY2yxyRy87lYo5OcRK1Kmg22+Ljn&#xA;T4cMccREdGwB6blqXYq7FXYq7FXYq7FXYq7FXYqsjKnlTqGPL54qgte0yTUtPa2jkEb8lYFuhp2N&#xA;MxNbpzmx8INIItLdQ8rTXOmWNolwoa0BDswNCGpWlPCm2Ymfs0zxwgD9KDFkKLxRVrXiAK/LNqBQ&#xA;pkxptPuIDrdxwljF3dwOhHpiqoI1LKSx223rTBEblkTsGTZJi7FXYq7FVO4jkliKRyGFmp+8UAsB&#xA;XeldqkYqhJtItfQb04RJPSqNM7sS3bk5LNiqAWDWrfgFST/dau0M3qITSsjencB2VQfsqrYqh47x&#xA;kvEu7m1RL1lQc5IZYyDJVQnNDOvLiNyOgyrwIcfHXq70Uv0fSgLia+s7mFfrXL4kYz0Xn8XAkRj7&#xA;Q6kHKcGihimZi7koFO80aTFLpRtSjXdxfSR24ef1ZQA5+JisQIQcQdwFHjmTPkzjzdpel2Emt6jc&#xA;2yLALcx20b2zsKGNeTAoKR9WoRQ7jJMWR4q7FUDqGtafp8sMd3J6fr1CNSoqKdab718Mxs+rx4iB&#xA;M1xIJpRh8z6JPcRW8FysjzGiFa0rWgFTTqdsrh2jhlIRjKyV4gmmZqXYq7FXYq7FXYq7FXYq7FXY&#xA;q7FXYqgbzSYbqUyPNOlUKcYpGQDlQFvhpvQUxVRPlyxLFjJcFuRdWM8hKsU9MEb7ELsMVcnlzTo6&#xA;em0ycSCoE0lBwFFFK9F6geOKt/4fsvhrLcHiEH9/KK+mSRWjeJrirX+G9MZlMwln4V4rNK7gEtzJ&#xA;oT1LAE4qmmKuxV2KuxV2KuxV2KupiqEn0jTZ2DS2yFwUIYCh/dnkm48Dviqi2kSohW0vp7c0IFSJ&#xA;gCzcmakoff54qr6fYmzikRpmneSR5WkcAGrmtKKAKDFUVirsVYj558v6vqs9m+nxh/RWQOS6rTkV&#xA;p1I8M0PbOhy55ROMcr6sJxJSTRvJvmS31iyubiBFggmR34ulAAdzxBzW6TsnUQzRlIDhBHUMRE29&#xA;JzsG12KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KsC88Xmq2f5ieQfquo3M&#xA;NnqF5d2l7p6Mot5UWxmmVnXjyLB0WnxU26Yqw3y/5q82NeeW/N1xrs1xF5n8wXeiXPlthF9Vt7ZH&#xA;uY4fRUKJFlh+qBnYsa8jXFU48y+dpdC/PO00tIri/uNY0O3g07TInCRmb67O8szlyI0EcMZLN9o0&#xA;oAcVY9+WnnTzS/5mzWeqahfyaRqd/r1lAt6EezaexuybaGydBzjdLeOTmJCAQPhqcVe8Yq7FUs8x&#xA;3fmC10t5tA0+HU9SDKI7S4uDaxlSfiJlEc3QduOKvNdG/ObzhP5pt9G1fyva2Vu+s/oC5uoNRado&#xA;7r6obyqxm2j5L6ffkN8Veu4q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F&#xA;XYq7FUu1Ly/pOpahpmo3kPqXejzPcadJzdfTkliaBzxUhWrHIR8QOKpVY/lt5KsfM8nma10xY9Zl&#xA;eSUzepKUWWYUmljhLGJJJBs7qoJ74qs1fyL5O8z6g2qanYtJqUKxWwnEssUsX1Sc3EJjMbrwZZGL&#xA;B13INCabZXjyCV+SrNF/KzyRo3mGXzDY2LjVZZbidZpbi4mSOS8YvcNDFJI0cRkLHlwUZYrJzcoL&#xA;pbYAtIVLtToqg0FfmemVnIOLh6qq5YrF/wAyliPlK6Mttql1EjI8keiXAtLsKrVLCYy24VFAq/x9&#xA;MVeQeQPMnku88xeX721s/OBgvdQkstOvtQ1X65p7XcUchZXRbyYOAqNvxI74q+h8VdirsVdirsVd&#xA;irsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVQuo6hDYWxnl37Ig6s3hlOozjFHi&#xA;KCWH3t9qc/K8blDDOeFUqqtw6A060985/NmyS9fIHuYEoFZZVbkrsG8QSDmMJEdUJxpms3lhMGvE&#xA;Z4rkBjI9eZUbAgnqBmfp9XPEfWLEvmyBZdHIkiLIhDI4BVh0IOb+MgRYZsA/PYov5c3bS2yXMAuL&#xA;QXBn9VraGJ7hEee5jhZHlhhDc2jrRqb7VwqwbyvdafP+ZWieYNG8vadc6XqNxLpVpq1vDcRSyG2s&#xA;gbnVIE5G0igLL6A+Hmw6ORtir3rFXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq&#xA;7FXYq7FXYqskmhjIEjqhbZeRAr8q5GUwOZVjnmq3vp7yJYYZJYkjqOCswDFjXoPADNR2lCcpigSK&#xA;7mEknNlrBiWE29wYlJZU4PQE9TSmYBw5qrhlXuKKKz9Gal/yyTf8i3/pkfy+T+bL5FaVJLPWJVRZ&#xA;Le4dYxxQFHNB4DbJSxZjViW3kVosl8ttcRac0d0jQ+k54+oCvwnf9qneubjs8yjjqW1HqyiqeYU8&#xA;w3Gkuvlu5s7fUmZfTmvonuIOFfjBSJ4mJI6fFmeDbJ5/e6R+df8AiHyq+oahp91o9vqivqMWjwXF&#xA;mywfVplrOZLiRXh5FRw4/a4nthV6pirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdir&#xA;sVdirsVdirsVYX5nZjq8gJqFVAo8BxB/XnO9ok+Kfg1y5oXUWZhalm5N9XQEn5mn4ZRnN8P9UKUH&#xA;mOh2Kth3X7LEfI4QSFRTyyHTEUuSpmYspPgq0/jl5kfDAv8Ai/QEqGq+br3yx5Pur2zhS61Ce7tb&#xA;DS7aYlYTdXsqwRmRhuEBfk1OwzadlE8J97KLUGteffKvmTQrDzVqVpruneZZ2sori2tfqUtneiF5&#xA;0UL6kolhdYmWpoymlc2rJ6PirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirs&#xA;VdirsVYV5m/47Ev+qn/ERnOdo/3x+DXLmhL8UFsfGBD+JGUZ/wCH+qFKFyhDsVdiqII/3HofGVh9&#xA;yrlx/ux7/wBSpN52uryLyLJbWltZ3Uuoarp1lw1FHlt0E1wg9VlR4W/dEBxRu2bbsr6Ze9nFPNP8&#xA;tfmbP5j0rU/Md75fvYNNeVozb2F1HcxiaMo5geS5kVGYbVKnao75tWTP8VdirsVdirsVdirsVdir&#xA;sVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirGdf0TULjUDcW6eokgUHcDiQKb1I8M02t0eSe&#xA;TiiLBYEJZrds1tNbwOatHAgYjpWprmHrMZgRE9IhBS7MNDsVdiqZ2mm3V7pRNuObxTGqVAJDKvSv&#xA;yzNxaeWTF6ekv0BNbKHmbT4LPyHqsGraPLrIvh6MOlQW4vJHldSsR9PdRRvi5E0Wla5tez8EscTx&#xA;dWUQxX8lfI35t6HFpzatqP6L0OK1hjuvLt3N+lZZJ1UCSVJf3f1QOxLCNJJFHhmeye0Yq7FXYq7F&#xA;XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqlWq+X4tQuFnMpjYLxIAqCAa&#xA;jw8cwdToRllxXSCLYheW4t7uWANyETFeXStDmgyw4JGPc1lM9R0BLTTluxMXLcfg40+171zNz6IY&#xA;8fHbIhDaNpa6jO8TSGPgvKoFe4HiMp0mm8WRF0gC2XaVpken25hRy5ZizMRTegH8M32m04xRoG2Y&#xA;FMU/Oc6kv5d6lLY3n1IQNBLev9ZWyaS0SdDcQpdOUELyxVRWr1NO+ZCWG+XD5qvPO+gXrayNPmuX&#xA;eZ/Kz6nFcejoMdpwtg1srv6888371p1Y8enIjFXtOKuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2&#xA;KuxV2KuxV2KuxV2KuxV2KuxV2KuxVhWraZfnVZ+MDuJXLIyqSCGNevTOc1WnyeKaBNlrIT/W7O5l&#xA;0UQxrzkj4FlXcniKGmbTWYpHDQ3IpkRsgPKlldRTzTSxtGnDgOQIqSQdq/LMbszDKMiSKFIiGS5u&#xA;GbHfP3lBfNnlx9JF19SnWe3u7S6MYmVJ7WZZoy8LFVkTklGUncYqx3Sfyhjh1bTNd1bU/r+u2uoz&#xA;atqF4lukH1ieS2+qQxrRneKCCLZYwxB74q9ExV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ku&#xA;xV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Kv/&#xA;2Q==</xapGImg:image>
- </rdf:li>
- </rdf:Alt>
- </xap:Thumbnails>
- </rdf:Description>
- <rdf:Description rdf:about=""
- xmlns:xapMM="http://ns.adobe.com/xap/1.0/mm/"
- xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#"
- xmlns:stMfs="http://ns.adobe.com/xap/1.0/sType/ManifestItem#">
- <xapMM:DocumentID>uuid:5705FAF2B22ADD1186FDF47D8AD4B8C4</xapMM:DocumentID>
- <xapMM:InstanceID>uuid:a26e4fda-9d51-f34c-a684-56c0b424aaa0</xapMM:InstanceID>
- <xapMM:DerivedFrom rdf:parseType="Resource">
- <stRef:instanceID>uuid:a2b8dcac-7818-4055-b6a1-3efa106255e8</stRef:instanceID>
- <stRef:documentID>uuid:9E3E5C9A8C81DB118734DB58FDDE4BA7</stRef:documentID>
- </xapMM:DerivedFrom>
- <xapMM:Manifest>
- <rdf:Seq>
- <rdf:li rdf:parseType="Resource">
- <stMfs:linkForm>EmbedByReference</stMfs:linkForm>
- <stMfs:reference rdf:parseType="Resource">
- <stRef:filePath>/Users/jason/Desktop/200x200_676640.jpg</stRef:filePath>
- <stRef:instanceID>uuid:0A6B9F33169711DC9044A943E0E0E870</stRef:instanceID>
- <stRef:documentID>uuid:5CEFDA43167111DC9044A943E0E0E870</stRef:documentID>
- </stMfs:reference>
- </rdf:li>
- </rdf:Seq>
- </xapMM:Manifest>
- </rdf:Description>
- <rdf:Description rdf:about=""
- xmlns:illustrator="http://ns.adobe.com/illustrator/1.0/">
- <illustrator:Type>Document</illustrator:Type>
- <illustrator:StartupProfile>Basic RGB</illustrator:StartupProfile>
- </rdf:Description>
- <rdf:Description rdf:about=""
- xmlns:xapTPg="http://ns.adobe.com/xap/1.0/t/pg/"
- xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#"
- xmlns:stFnt="http://ns.adobe.com/xap/1.0/sType/Font#"
- xmlns:xapG="http://ns.adobe.com/xap/1.0/g/">
- <xapTPg:NPages>1</xapTPg:NPages>
- <xapTPg:HasVisibleTransparency>True</xapTPg:HasVisibleTransparency>
- <xapTPg:HasVisibleOverprint>False</xapTPg:HasVisibleOverprint>
- <xapTPg:MaxPageSize rdf:parseType="Resource">
- <stDim:w>600.000000</stDim:w>
- <stDim:h>800.000000</stDim:h>
- <stDim:unit>Points</stDim:unit>
- </xapTPg:MaxPageSize>
- <xapTPg:Fonts>
- <rdf:Bag>
- <rdf:li rdf:parseType="Resource">
- <stFnt:fontName>MyriadPro-Regular</stFnt:fontName>
- <stFnt:fontFamily>Myriad Pro</stFnt:fontFamily>
- <stFnt:fontFace>Regular</stFnt:fontFace>
- <stFnt:fontType>Open Type</stFnt:fontType>
- <stFnt:versionString>Version 2.007;PS 002.000;Core 1.0.38;makeotf.lib1.7.9032</stFnt:versionString>
- <stFnt:composite>False</stFnt:composite>
- <stFnt:fontFileName>MyriadPro-Regular.otf</stFnt:fontFileName>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <stFnt:fontName>Futura-Medium</stFnt:fontName>
- <stFnt:fontFamily>Futura</stFnt:fontFamily>
- <stFnt:fontFace>Medium</stFnt:fontFace>
- <stFnt:fontType>TrueType</stFnt:fontType>
- <stFnt:versionString>6.0d3e1</stFnt:versionString>
- <stFnt:composite>False</stFnt:composite>
- <stFnt:fontFileName>Futura.dfont</stFnt:fontFileName>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <stFnt:fontName>ArialMT</stFnt:fontName>
- <stFnt:fontFamily>Arial</stFnt:fontFamily>
- <stFnt:fontFace>Regular</stFnt:fontFace>
- <stFnt:fontType>Open Type</stFnt:fontType>
- <stFnt:versionString>Version 5.01.2x</stFnt:versionString>
- <stFnt:composite>False</stFnt:composite>
- <stFnt:fontFileName>Arial.ttf</stFnt:fontFileName>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <stFnt:fontName>BookmanOldStyle-Bold</stFnt:fontName>
- <stFnt:fontFamily>Bookman Old Style</stFnt:fontFamily>
- <stFnt:fontFace>Bold</stFnt:fontFace>
- <stFnt:fontType>TrueType</stFnt:fontType>
- <stFnt:versionString>Version 2.35</stFnt:versionString>
- <stFnt:composite>False</stFnt:composite>
- <stFnt:fontFileName>Bookman Old Style</stFnt:fontFileName>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <stFnt:fontName>BookmanOldStyle</stFnt:fontName>
- <stFnt:fontFamily>Bookman Old Style</stFnt:fontFamily>
- <stFnt:fontFace>Regular</stFnt:fontFace>
- <stFnt:fontType>TrueType</stFnt:fontType>
- <stFnt:versionString>Version 2.35</stFnt:versionString>
- <stFnt:composite>False</stFnt:composite>
- <stFnt:fontFileName>Bookman Old Style</stFnt:fontFileName>
- </rdf:li>
- </rdf:Bag>
- </xapTPg:Fonts>
- <xapTPg:PlateNames>
- <rdf:Seq>
- <rdf:li>Cyan</rdf:li>
- <rdf:li>Magenta</rdf:li>
- <rdf:li>Yellow</rdf:li>
- <rdf:li>Black</rdf:li>
- </rdf:Seq>
- </xapTPg:PlateNames>
- <xapTPg:SwatchGroups>
- <rdf:Seq>
- <rdf:li rdf:parseType="Resource">
- <xapG:groupName>Default Swatch Group</xapG:groupName>
- <xapG:groupType>0</xapG:groupType>
- <xapG:Colorants>
- <rdf:Seq>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>White</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>255</xapG:red>
- <xapG:green>255</xapG:green>
- <xapG:blue>255</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>Black</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>0</xapG:green>
- <xapG:blue>0</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>RGB Red</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>255</xapG:red>
- <xapG:green>0</xapG:green>
- <xapG:blue>0</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>RGB Yellow</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>255</xapG:red>
- <xapG:green>255</xapG:green>
- <xapG:blue>0</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>RGB Green</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>255</xapG:green>
- <xapG:blue>0</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>RGB Cyan</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>255</xapG:green>
- <xapG:blue>255</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>RGB Blue</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>0</xapG:green>
- <xapG:blue>255</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>RGB Magenta</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>255</xapG:red>
- <xapG:green>0</xapG:green>
- <xapG:blue>255</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=193 G=39 B=45</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>193</xapG:red>
- <xapG:green>39</xapG:green>
- <xapG:blue>45</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=237 G=28 B=36</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>237</xapG:red>
- <xapG:green>28</xapG:green>
- <xapG:blue>36</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=241 G=90 B=36</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>241</xapG:red>
- <xapG:green>90</xapG:green>
- <xapG:blue>36</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=247 G=147 B=30</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>247</xapG:red>
- <xapG:green>147</xapG:green>
- <xapG:blue>30</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=251 G=176 B=59</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>251</xapG:red>
- <xapG:green>176</xapG:green>
- <xapG:blue>59</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=252 G=238 B=33</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>252</xapG:red>
- <xapG:green>238</xapG:green>
- <xapG:blue>33</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=217 G=224 B=33</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>217</xapG:red>
- <xapG:green>224</xapG:green>
- <xapG:blue>33</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=140 G=198 B=63</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>140</xapG:red>
- <xapG:green>198</xapG:green>
- <xapG:blue>63</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=57 G=181 B=74</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>57</xapG:red>
- <xapG:green>181</xapG:green>
- <xapG:blue>74</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=0 G=146 B=69</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>146</xapG:green>
- <xapG:blue>69</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=0 G=104 B=55</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>104</xapG:green>
- <xapG:blue>55</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=34 G=181 B=115</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>34</xapG:red>
- <xapG:green>181</xapG:green>
- <xapG:blue>115</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=0 G=169 B=157</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>169</xapG:green>
- <xapG:blue>157</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=41 G=171 B=226</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>41</xapG:red>
- <xapG:green>171</xapG:green>
- <xapG:blue>226</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=0 G=113 B=188</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>0</xapG:red>
- <xapG:green>113</xapG:green>
- <xapG:blue>188</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=46 G=49 B=146</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>46</xapG:red>
- <xapG:green>49</xapG:green>
- <xapG:blue>146</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=27 G=20 B=100</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>27</xapG:red>
- <xapG:green>20</xapG:green>
- <xapG:blue>100</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=102 G=45 B=145</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>102</xapG:red>
- <xapG:green>45</xapG:green>
- <xapG:blue>145</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=147 G=39 B=143</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>147</xapG:red>
- <xapG:green>39</xapG:green>
- <xapG:blue>143</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=158 G=0 B=93</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>158</xapG:red>
- <xapG:green>0</xapG:green>
- <xapG:blue>93</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=212 G=20 B=90</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>212</xapG:red>
- <xapG:green>20</xapG:green>
- <xapG:blue>90</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=237 G=30 B=121</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>237</xapG:red>
- <xapG:green>30</xapG:green>
- <xapG:blue>121</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=199 G=178 B=153</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>199</xapG:red>
- <xapG:green>178</xapG:green>
- <xapG:blue>153</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=153 G=134 B=117</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>153</xapG:red>
- <xapG:green>134</xapG:green>
- <xapG:blue>117</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=115 G=99 B=87</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>115</xapG:red>
- <xapG:green>99</xapG:green>
- <xapG:blue>87</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=83 G=71 B=65</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>83</xapG:red>
- <xapG:green>71</xapG:green>
- <xapG:blue>65</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=198 G=156 B=109</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>198</xapG:red>
- <xapG:green>156</xapG:green>
- <xapG:blue>109</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=166 G=124 B=82</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>166</xapG:red>
- <xapG:green>124</xapG:green>
- <xapG:blue>82</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=140 G=98 B=57</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>140</xapG:red>
- <xapG:green>98</xapG:green>
- <xapG:blue>57</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=117 G=76 B=36</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>117</xapG:red>
- <xapG:green>76</xapG:green>
- <xapG:blue>36</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=96 G=56 B=19</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>96</xapG:red>
- <xapG:green>56</xapG:green>
- <xapG:blue>19</xapG:blue>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=66 G=33 B=11</xapG:swatchName>
- <xapG:mode>RGB</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:red>66</xapG:red>
- <xapG:green>33</xapG:green>
- <xapG:blue>11</xapG:blue>
- </rdf:li>
- </rdf:Seq>
- </xapG:Colorants>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:groupName>Grayscale</xapG:groupName>
- <xapG:groupType>1</xapG:groupType>
- <xapG:Colorants>
- <rdf:Seq>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=100</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>255</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=90</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>229</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=80</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>204</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=70</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>178</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=60</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>153</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=50</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>127</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=40</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>101</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=30</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>76</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=20</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>50</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>K=10</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>25</xapG:gray>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <xapG:swatchName>R=241 G=241 B=242</xapG:swatchName>
- <xapG:mode>GRAY</xapG:mode>
- <xapG:type>PROCESS</xapG:type>
- <xapG:gray>12</xapG:gray>
- </rdf:li>
- </rdf:Seq>
- </xapG:Colorants>
- </rdf:li>
- </rdf:Seq>
- </xapTPg:SwatchGroups>
- </rdf:Description>
- </rdf:RDF>
-</x:xmpmeta>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<?xpacket end="w"?> endstream endobj 2 0 obj <</Count 1/Type/Pages/Kids[5 0 R]>> endobj 13 0 obj <</Intent 14 0 R/Usage 15 0 R/Name(Layer 2)/Type/OCG>> endobj 17 0 obj <</Intent 18 0 R/Usage 19 0 R/Name(Layer 3)/Type/OCG>> endobj 33 0 obj <</Intent 34 0 R/Usage 35 0 R/Name(Layer 2)/Type/OCG>> endobj 37 0 obj <</Intent 38 0 R/Usage 39 0 R/Name(Layer 3)/Type/OCG>> endobj 61 0 obj <</Intent 62 0 R/Usage 63 0 R/Name(Layer 2)/Type/OCG>> endobj 64 0 obj <</Intent 65 0 R/Usage 66 0 R/Name(Layer 3)/Type/OCG>> endobj 83 0 obj <</Intent 84 0 R/Usage 85 0 R/Name(Layer 2)/Type/OCG>> endobj 86 0 obj <</Intent 87 0 R/Usage 88 0 R/Name(Layer 3)/Type/OCG>> endobj 112 0 obj <</Intent 113 0 R/Usage 114 0 R/Name(Layer 2)/Type/OCG>> endobj 115 0 obj <</Intent 116 0 R/Usage 117 0 R/Name(Layer 3)/Type/OCG>> endobj 218 0 obj <</Intent 219 0 R/Usage 220 0 R/Name(Layer 2)/Type/OCG>> endobj 221 0 obj <</Intent 222 0 R/Usage 223 0 R/Name(Layer 3)/Type/OCG>> endobj 325 0 obj <</Intent 326 0 R/Usage 327 0 R/Name(Layer 2)/Type/OCG>> endobj 328 0 obj <</Intent 329 0 R/Usage 330 0 R/Name(Layer 3)/Type/OCG>> endobj 462 0 obj <</Intent 463 0 R/Usage 464 0 R/Name(Layer 2)/Type/OCG>> endobj 465 0 obj <</Intent 466 0 R/Usage 467 0 R/Name(Layer 3)/Type/OCG>> endobj 609 0 obj <</Intent 610 0 R/Usage 611 0 R/Name(Layer 2)/Type/OCG>> endobj 612 0 obj <</Intent 613 0 R/Usage 614 0 R/Name(Layer 3)/Type/OCG>> endobj 729 0 obj <</Intent 730 0 R/Usage 731 0 R/Name(Layer 2)/Type/OCG>> endobj 732 0 obj <</Intent 733 0 R/Usage 734 0 R/Name(Layer 3)/Type/OCG>> endobj 733 0 obj [/View/Design] endobj 734 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 730 0 obj [/View/Design] endobj 731 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 613 0 obj [/View/Design] endobj 614 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 610 0 obj [/View/Design] endobj 611 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 466 0 obj [/View/Design] endobj 467 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 463 0 obj [/View/Design] endobj 464 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 329 0 obj [/View/Design] endobj 330 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 326 0 obj [/View/Design] endobj 327 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 222 0 obj [/View/Design] endobj 223 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 219 0 obj [/View/Design] endobj 220 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 116 0 obj [/View/Design] endobj 117 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 113 0 obj [/View/Design] endobj 114 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 87 0 obj [/View/Design] endobj 88 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 84 0 obj [/View/Design] endobj 85 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 65 0 obj [/View/Design] endobj 66 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 62 0 obj [/View/Design] endobj 63 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 38 0 obj [/View/Design] endobj 39 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 34 0 obj [/View/Design] endobj 35 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 18 0 obj [/View/Design] endobj 19 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 14 0 obj [/View/Design] endobj 15 0 obj <</CreatorInfo<</Subtype/Artwork/Creator(Adobe Illustrator 13.0)>>>> endobj 728 0 obj [732 0 R 729 0 R] endobj 5 0 obj <</Parent 2 0 R/Contents 829 0 R/BleedBox[0.0 0.0 600.0 800.0]/PieceInfo<</Illustrator 719 0 R>>/ArtBox[0.0 0.0 600.0 800.0]/Group 830 0 R/MediaBox[0.0 0.0 600.0 800.0]/Thumb 837 0 R/TrimBox[0.0 0.0 600.0 800.0]/Resources<</XObject<</Im0 737 0 R/Fm0 765 0 R/Fm1 771 0 R/Fm2 777 0 R/Fm3 783 0 R/Fm4 789 0 R/Fm5 795 0 R/Fm6 801 0 R/Fm7 807 0 R/Fm8 813 0 R>>/Shading<</Sh0 739 0 R>>/Font<</TT0 814 0 R/TT1 816 0 R/TT2 818 0 R>>/ProcSet[/PDF/Text/ImageC]/Properties<</MC0 729 0 R/MC1 732 0 R>>/ExtGState<</GS0 770 0 R/GS1 820 0 R/GS2 821 0 R/GS3 822 0 R/GS4 823 0 R/GS5 824 0 R/GS6 825 0 R/GS7 826 0 R/GS8 827 0 R/GS9 828 0 R>>>>/Type/Page/LastModified(D:20080601013506-07'00')>> endobj 829 0 obj <</Length 6764/Filter/FlateDecode>>stream
-H‰\—Ën.·„÷ÿSÌ hÄnÞ·¾ÄÈÂ/âýA`/ŽØ~ _Gdž!HÎ}­®n¾ÿãëëýû¯ËõÕ7__¯o¿çÏûyçÕ¯¯rõWíåÊÜ×oÿyýûú/¯ß¿û¡\?ýþj|ÐOöu½E9»?ýòzÿû/åúæ¯òóë«ÎyÍ×/<•»ÎêUýškÜ#çó\®O¯§Ï~(ýxJŸü0‚SÈÕÿO¯§Ï¯<IÏç×ϱºŽ{Õ¾6ÛÞ²¬{NÔ¿.þ´«Í¼ËÊR#¯¥==GSž~õãõþÃÏåúýçëÛ¯ãoaVðû¦‡'j'RÿúîÕ®ï¯/¶üz…ßVû‹P½Ðß··n—ßÐþñûéõ–uûñ3­Ÿúš=¾Ôsñf‚ßÏóÙðœŒ|IÔû¤'¶ÝZ”/ÇŠe}²
-ïv—B.½ÿí#ù(âç·Ÿþäeîq—Ù•þyÏÒãßò}_äWhj÷&yíÎl
-ÀR†ïÖ‡¬›w´qí{ÈêuŠš¸÷P@â^{\ë.Í[£"®q4—"Wï¾ç•ü%HA†1 Þ±ÃA
-«nw©ŠF`h»¢Ý³w…—ÄæÍ˜_û‰ ôÖrG`Rä`(¸&XÚÚZë=Ñ0î(øRûi„¡•=TÃÝÂ2ç*Ë]ûX¶
-(×u02„ÃÅÛ9{]IĬu8d±ïº·eGTê–P¬í!‰ÁðçV8ÜîžËÂUáx9ê±EFô+‰¤2Ðë½|V*?»7†Ö:”: dXë-Ç¥¾{;æïU·
-Odj¹^#ecBS"³sQƒ` IKÝ÷j,+ÕyìnÄ cí— 4bÚ±¥iQw½3NfJË«ƒêrrŽ6¬êûn­[zpzTrTidrÒ“ô}o04óEÞ³‘¿@Ç6DK'¤#žÂzÀB÷ !
-[ê†ڽì a‘~¶“Yj NÌT!OlZó^EËF|XŠ¢æ× w!ƒB>õ
-ÝLTbÊ:¥Ä›ÝoT\ôªÄjˆþîÚSÁ®ÒmZ›t̹lc
-“?P:Žo ~Ðy—8/x'üÊ*»7<Æ-Tô€Rk Âb¯@µ‰BUT`kúXöÆ0ŠK º­·i5ÁâxjªXÚKÐÔ|BQ¡×cô\6Þ³
-‚›PSÂf6®ÚŒ[2еHíLMŒzëVW¢™ØŸ£5KK¦± …šª0õ+
-@Fj©ÑóU)°u^tŽáÚXû8ÆhR®rvCûv‹òkªyMÓ‡ºÚ|Lqqá<`7¨‘±ÎwTJc*(4®®Ú¥èGwȧâÌ‘HÀÕV“æé çÓ‹ŠíO¶ç[l B:ˆlMo7úU¢ ¦Y»ÛÛÐh´×@8 IŒ+]$Èè”+Umïj±i] LéO¹ÂA
-ÓKeÞ¼}ãð*nÔ‚‘zíÂ}„²)AjH¤XÃí¨”´îIÑêñš™™Ý›4Ϩ€[1ÎYb¥îÓ5”åôÐÂàpÀ¤1F³•UUz¶Ó|”–ÂAWhnÁع—»ÍT1¬™ÁïEˆP¯Ùê„—ÆIâÔmÄ?ê-íØ$FAÚ¬JªxòŒo*dYÉA­‡JYäþô
-©’Àê994L µ€Ý,Fà‡Ö*iµ³–FÖ3Ï Ê{-û­&ÛTŒÝVk|7úÃòÆrœÚò4œši¡­CX¥°ºáÅMóêñ¢«é Km¹kHŸûiD’Fâ—åÀFqRdi*­WÛ”Ý÷Rµý]Ã6'†æö<2B—œaB3ÝXtк/çbоÇysË(Ç&U½:Ëh‡'«gvZDì'öIñ0%:n1Ý<Ôi~ Ú¢Lå ‰ÃÜ0ÚQ¡éf‹sOT”Kø§ˆ+‡iÛ“€(7Vñ¿º@9}Bw&¿èJKõ·Ê)ú@³°ª÷Óc¥¯cž¶1ò>e<má8‘¹ò>Õ/©Ûqå¾ó í½½ö¬ š)Õã¦H)ÔëšÛávΘÕ}€R7ùKd!bAyÙ¦[ÆéÆ|Ráuî?:
-н³{=ûðºÃ[Á|®1J‘Õ%Q"âñ3Î :I¦"‰š§†æ*'/4 L¿Éù¡´³îω¦®ÆZc±Nè
-ÑÎMŠ¥wœéJ߻ƞQŸ ‹0ÏX6ã ²_k Jô»©'4‡ªhFJŠ® Ê\èêÜgˆhžB©ã8-¹œ¹T×T!Å¡Ö Z>-=˜O¨XTYM"3ÍWF±J&!ˆØBíá[Mõ|ÔêZÜçU'½nfƒýÜOM‚a‰»œuzoË”¾æ©#ˆ™¢ÁчÁªY+WjˆFƒî*QTÂÝ*„A.=Ûð÷ŒF»DñÐ%aŸaŸ8 ZZð=rùP±ÜCaw-¨iBγ ?ÙÍ¿~Jk ÃÃë0o4Øt®¶T㣠¦.?ÝC®†]!Uu¸4,\cy"”lÀ$¥>¾Žjy. 9²ˆìÍF&1,Ä\c½ÚºÊ¹ÄF9ELiB×ÝE áA&¸B xˆˆ°¦ïå1l"
-öyÜÄR6“…v´
-¥ßl=u%œÃܤ¦jÈSÙPµ ­ÎÕJëNè5"É--›ër¨e£ãi¤+îÒ¦ï÷­âX‰xk¾t
-K;ìYNBÉ©y³çÚåÜnñ([W;ý¿h*‡³èÚ„q–UrSÚA¥qF·Î]Y¾JŸä쨢}<I?=€ª4%ÌŒ&8ríùàZšÖh ßÇ ÓCÆ3ñÞÑÇéãºözªðä'æó2r6‰}Ó÷ÅE<à
-Eª©´K† •”¾ YLÊ¥]Bòć§Œã¦Ù_ãˆm€zJìb”µºÞë#ûz‚GFG¶øÈ­j‹Kïj“CµÑŒmîIcй[»åZw´¬ÅvÝRä*tÇÿ.U<û¼’v¹Uzo}¯û¾ƒÒ Ô<QY…ïÇ“›AÿWF‚Û‰Í J
-RʖÇbÖV?gf°8Ð#j h<ïÙAmYûÒ]þ¹¥Ñžý¶šèË·å›ÛªÜš
-ÿ²w^®_{Ÿ´ZßÍ@ήÞ´™šæé=Òj2^qú+T ^áõ›apô@ïD96»a3–©A?Àšc›Q÷=9<Žä]oôÙñŽ•ƒ÷º³_|ÊB¯†[Zd/3àTÌÇ% ³3o.†‰ ³óö¨ùé…uka’B ÿœIÙDªÃÇÝ»1îèJ c5`IJXB6Çs ¢@ùxñf‹àú"âÞ÷´?è;àoßů j†ç׸°ð›‘!Ðz¦8V9ì„•{¯´9!Ñʈ
-}¬ŒQ„0>¥NŸ^„°3Ãë= DíÑÊR$´¦E¸Ó
-?½H!ýt
-€÷v’`ôr2
-œ}Õnì¯Ã¼×L±!.uB„•è}¨À ¤äˆƒI1dçm,Õ]J"¯CµúîÂà*´2ºg‡Ô£J×äÎã™èÀaB—¼•1Ý£anM/á¸c•m-œÇR™6W“]j³‡ÇùÙ]F0ieÀ:98a:rñ$fæeš?M¯Ïp/<¦‚­Hpȹ,5xWâ c3rð’ÓnEQ–Å‚éʼn¤mOÞãná6p1 ¾Þ¢{e77Ú¯3IYRpSSOG¾ºŸé€a›FίK9¯
-Ìۋ¨PIFƹFbë5²¼¡CmïÈE}°4’½gŸlã :]2DE€-ºê@× “Šƒ»Ì6gÍg&¶ÜôÔž»í’ܰ©Zëã@'5í¨ÓÓ1©ÐÖÁ!Sê†Ëª‘
-yѵœ…lÙ膤’»b.÷P<¢³—­pk.ç΢ »UvqOÝàu&\q5D¨¢j$ÁS/¨F+ýÁY›[å­ëÎÏR©cŒÒmIeÆS„3®Än&jäöZ-Èë(µJï³? z§ž=Wʋ˺^ÄÜè<÷v–Mž|­6UÀNÑ/=•çØàf\¡l4^䈮yЪèÇyi:hî”è@mZ º[ñMè‡%˜
-ÒJT÷Ÿ:Ôí)İi†2ÍMGìR%ñ‘-Sf¤í©t ã+R¡^3Ämí'­\UË÷¾À¯Ñ÷í“æ¦N¥äµÇVÕfW–ØJ
-šâÒØðHC¨«<‚L¥O„Ž€¡ì&ÑAúÁPÝt]ÆzÕÉh£MæR¾Ñ(OäshÙ¶wÌ6Hg=_p[H;×ÚÐEm˜éHT:>ƒv÷éU|B(íN×P—uã©*ÆÔι
-¶½NÚ‘²±_y Ž"h7H9Z@_Ãež™fJ7ëhï^ŠÄI#Nrœ¢<ò(¯ðJ¡‘ÎsCpPÍ{ÜI+˜ˆÔqÖ+=ãê5³¿yµ:GÁZ¹·B™/„±¯üº†|‚JµAm+›õlËÐHU¹”Zà{Šg&‚û.»Î+s ‰š‘ég¯žÔJRUÖÌ©{âºk\­ã¦úË¡‰*“¨<órNÓÙóIBϨtÿØykÎL–MP^Ç4WO¸Ô~ë¨Á¼Ö¢Òõ"”1ÒwµT{®­S®¯©Ã¢m3Ù=A€v§4Pcu5Mš¶GÔ@8ªyí&ްS_s%-=z‘B znq;Òε£œVÛ ÜY–°ƒº­Ý“ü4x õÍ_Êbû=z
-š ps&ÑÞ÷zΨBV5þÜC?Õ±‹í*‰ª¹#Ñ:éüâŒè².ñ{¯a&Jyiö¾g`-¯–/D¡<vòK77àÓqr^;Ùõ
-÷“ËÎ.§Üy2Q®kF7|¢$¨š”½®q¤­YRâ¤'öÞ|°W
-UYʪ»'‡û‹ÁM›ªÇÜÄŸ(7ÈȺSÁù*I‘s*ÆôB„uP›c›¶aÇŽ²"oÄ0r:t©$åœLÉÞ4„“\M£cÖœqEAü—æ2è‘£¢ð}~Ew‘F±Ým·}$!A 8ÀÎ qŠ”P„€ÿ/ñ}U=Úì{zìrÕ«Wï…JËôÁqpÄ™™ÂxrëQ¿ýÌ{:xŒÖß+ckÏê,«22¦*ñqfˆÞØ{Pæ^ÎD
-úŠÐòëªÅ M„“ÈRX$¹Äi`š*ikŠ ‘—àlø¤λ3Ê;HÛ“y]w
-TŠË\ì1H¸=ºeØÏ-6ï€DA™Ti³‘/µÛèÛ³“XJ×.-ãˆyB5>]Ó²r8€  qÎ4–ƒ-»þ¸HØ }hÃZ6äNhãÒ>9¹æ›áz#¤PØ;KhžÑ—ÙŒŽµÞ%ç¥3Œ`ÚžÔºË
-8;Z\79p2P"&GA5+1HEQ]aXhIr=ZrjD8'-?j<K`R07]u?o)c/fLf$)A'F]ZU*i9QGb
-7ZB.[B#BW_VH>Y>V9L]-3g(#be,$5T:@hBX^fh"<dF5@ro7>1o6,7VG`qKfLU\1?c
-N3(9KKr!FbNCPoP;Q<E)FBcf[M@>gmU9u^,;8S8J<\]XPo49uD,snHp2.i#6HB-Oo
-UB_*/(K9$I5@*ARAY%0Q@b&@LN\teBbTFD$Y%:j>Ki]R.@i:9-4O0`8rjMb,X8EB1
-'CZ_2.g"#3.]KJ*_e:ub)LcJ]dlD#D#fj6[BQI4G9cM?][1ceAYt$(-f%#_=@t\_^
-<p+4pS+(`=%U#W#8!kq3HZpB$>]*<]S"A0\_uX,'6#L^!PSUf8?kom`22<#^do(9A
-\tercL$P5Z<K9qpWn4Qga@Y!)<e8[J/j2f^<asD0B2Vf/7t,MV_f%+Y'IqJARJ&O,
-Q;u-USgd!7#2@0KM#m#:B2Vf"b/T3JAbVb&GZ3Eq#&+]RCDK.ZV5+MX-Y*lh9cZ&f
-:[?35Q1pk$9q]oRb[sml_nEKFPiQf;>bdFXCFPZ^g`m5'`9ED"J5[4]Pd*?A:C<IT
-GV8ko``o4bbO_^mcREd6<3!JY3%BDR#i=?ADs:LaTN(Mr'_6k\]P#ue5d$_7l<Jm8
-kbOJ^^_[:fbP&4k2:\+"@%c:Fb18!U_uUEI6rk,^oS?u)O9m1Kfr-FFl,+u>rZTU%
-T.M=4oL`,K4eq&/\W%B'<.+b@X0!VH5A!NM>&s=u>r/N4nVA4O_<e*rT2db8l;FV$
-qh8&b>;UOgNu8nKL6W9Ic9^j+\QT5'XJK+"9(#S_H5h(%F&^G.huZ?7@r6d%B&&#$
-XLK)5_s4FYJCUDBr#9Q1H;^G/e#cpA(VHBFP"7#pP2>&3*7A'fQ,6hYcngn)^*jRl
-.NP+m/#Xii-"0*"Piu'`a'O/=ZDlqO8qoMc=Xi!JmgT1!]UscQDf^9s)]:ktrKhM4
-hYZG)-kejW\_7!/gJESk+a/bGni<#0<^s<dV?sCk0eAQ[-MX_CFY`bpZ?o6Zb`9I$
-NI"'Hj/[U09QL^sma7;,&[":I'8%8aVF\>M6T+UMN4<TZWiB^kLTuA$l7iouJhp.V
-Y<CXu:1##m;KSG%pabPg"FT^[UCj!EB%4q<(Nj2lasn.+`NT!.T&TMG<]m<OUXZQ>
-_e%o8_J7A5L!tWGMi+XCg2cPi]mbkh-&OF7S]T$ggGY_5Q"mg*hoCVT'uSZS\8BI$
-ib[d@>&CSAD65e!R!%Nac+a8Z0J;d@~> endstream endobj 770 0 obj <</OPM 1/BM/Normal/CA 1.0/OP false/SMask/None/ca 1.0/AIS false/op false/Type/ExtGState/SA true>> endobj 820 0 obj <</OPM 1/BM/Multiply/CA 0.5/OP false/SMask/None/ca 0.5/AIS true/op false/Type/ExtGState/SA true>> endobj 821 0 obj <</OPM 1/BM/Normal/CA 0.75/OP false/SMask/None/ca 0.75/AIS false/op false/Type/ExtGState/SA true>> endobj 822 0 obj <</OPM 1/BM/Normal/CA 0.649994/OP false/SMask/None/ca 0.649994/AIS false/op false/Type/ExtGState/SA true>> endobj 823 0 obj <</OPM 1/BM/Normal/CA 0.550003/OP false/SMask/None/ca 0.550003/AIS false/op false/Type/ExtGState/SA true>> endobj 824 0 obj <</OPM 1/BM/Normal/CA 0.5/OP false/SMask/None/ca 0.5/AIS false/op false/Type/ExtGState/SA true>> endobj 825 0 obj <</OPM 1/BM/Normal/CA 0.449997/OP false/SMask/None/ca 0.449997/AIS false/op false/Type/ExtGState/SA true>> endobj 826 0 obj <</OPM 1/BM/Normal/CA 0.399994/OP false/SMask/None/ca 0.399994/AIS false/op false/Type/ExtGState/SA true>> endobj 827 0 obj <</OPM 1/BM/Normal/CA 0.350006/OP false/SMask/None/ca 0.350006/AIS false/op false/Type/ExtGState/SA true>> endobj 828 0 obj <</OPM 1/BM/Normal/CA 0.600006/OP false/SMask/None/ca 0.600006/AIS false/op false/Type/ExtGState/SA true>> endobj 814 0 obj <</Subtype/TrueType/FontDescriptor 815 0 R/LastChar 107/Widths[320 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 620 620 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 680 740 740 0 720 640 0 0 340 0 0 600 0 740 800 0 0 720 660 620 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 620]/BaseFont/PRXEFX+BookmanOldStyle/FirstChar 32/Encoding/WinAnsiEncoding/Type/Font>> endobj 816 0 obj <</Subtype/TrueType/FontDescriptor 817 0 R/LastChar 77/Widths[720 0 0 0 720 0 0 0 400 0 0 640 940]/BaseFont/PRXEFX+BookmanOldStyle-Bold/FirstChar 65/Encoding/WinAnsiEncoding/Type/Font>> endobj 818 0 obj <</Subtype/TrueType/FontDescriptor 819 0 R/LastChar 107/Widths[309 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 617 617 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 741 591 701 0 0 508 0 0 295 0 0 443 0 0 0 0 0 602 583 482 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 498]/BaseFont/PRXEFX+Futura-Medium/FirstChar 32/Encoding/WinAnsiEncoding/Type/Font>> endobj 819 0 obj <</StemV 112/FontName/PRXEFX+Futura-Medium/FontFile2 834 0 R/FontStretch/Normal/FontWeight 500/Flags 32/Descent -289/FontBBox[-524 -289 1322 1057]/Ascent 1057/FontFamily(Futura)/CapHeight 754/XHeight 476/Type/FontDescriptor/ItalicAngle 0>> endobj 834 0 obj <</Length 6763/Filter/FlateDecode/Length1 11697>>stream
-H‰ŒV XTe~¿s†a@±AQL¼œŒ‹Pñ.¨ˆ"ŠéŒWPPPQT¼•¥«e2[êš›×,1•¶Ñ­Äm­]SÓ\Ûm[¯ ÛªYÞºhšÎLï9å>Ïvxþóÿÿ÷|ÿwyßï @–BEưÌñ ²Îm¦ä,ǨÉÙ…{WŸO$0?9y~‘Öè–_à_ÎóvS
-§ÉÚ³ûO©“9uÆ¢)W«J>¢(KÊËÍι´8º-`Jý®y4ºÂý&îÛæ-ìo[N}ëû´ÿöŒY“³KVlÈ
-7p_Dü%@J#i*¡ÒJÚˆM"$J“8é ÒKúH’ô—2DÒ%C2e´Œ—‰2UòeºÈ\™' é{s¥Jù¾ŸTΨPÍj ù3ß›h͵–šføÞý¾Ó÷Gë}Ï1|úÞÐÀwŸU»ë;É8¬øå³Øwç!ÙÃO+düOyGZîx†p¼çm x‹¼s½s8;¼©žbÏ<O`Í÷5ßÔܨ¹^s­æËš 5§jNœÏ­ÙRSV}°úXõ> ú GYõÖêâêIÕÙg‚,E~§k1d<{·ÛïâœÇ%x‰#æ¼ñ¢#%Z:)¥óÝŸIŒ8d‚¡•%9ÄI‘Ì—ge…¬—¬£T›kßk¯“Ò_‘ZÍ¢ÚñУ¢½<‡ÛxŸãþC¤o‡¥çÿÅE”á~À¼Ø‰ÝØ…ròáM¼…?0Æ=ø#c~ïà{Æ[?¡UdÑgDÝŸ±ïá/¸‹{8É蜌6•ë"ЍŒ­/Ùч%ce±Œ%KzIÙ3„1ÿ^øäy‘|/«dµì–rY#¿c~&ÉZy‰ŒšÈÄ_–RÙ ¿—fm¶¬#ûK.¹ÖUe£lÂw¸E<#~óÈÉ yƒùN>üKºË "z†$3ÿq¬Ç˲žŒnŠ›øFÊär'Ù)»d«¼JÜÏ”mò9IfŒ”YR(¯ã£W±¾Æ·dÖ2|AŽ]Ç\“岇É7+{‡Y 4j€RWæÿ§:üŸÖW+ -‰ðÖhC†ÛÈñp´E"…vx шA,âЈ÷NˆG:£ º"Ýн­'z¡7ú /»e?ôÇãHF
-` !ƒ‘†!Št #‹†c21O`FÃ'Æ`,Æa<&`"²I˜Œäb
-ûoò1 Ó1˜‰Y(ÄlÌÁ\aæcý߈MØ‚W‰µíDÖ¢j'µ›˜z“xzË@Ô^bJGÔ»DSñ´ˆÚO4éX
-ÂJ<‰§°`Q¹¿Áûx]ûl&fÿ†bćx/âó±/ÃZöÁ‰ÉõX„gY‘øÿÀr¼Ä£âl ê‰ ýKƒ@4€?{ègø7NâB$Ñ„ô,ûÓj~"˜ß¦m(Ákì°çPrˆÜ‘¹äΚK¸L,\Áóüf|…«XƒkÄÅ VçeÆ{g¤WGq‰30ÅsŠzaf Z›Ì(ª
-=±9ãøÉ?LþtcŠU–7u+MöÅÐ ë>úkÅJÈ!ÅÁ„v«¤‚µ³N
-\T!”7EÿjÕRÉ6­W \iF>‚õšéMCükßfÖOMˆgá"c$ø§ÆHåÆOêµä©ƒ–ÍÊß¼0uÙ¢ÅóG¬Ù<8=-uÿ|³¥yóî=αes£óó\ïüÈ~•ÆFu]á{ß6c›ŒYmškl0‹=Œ Ævh€°ì’‡”ˆ‡ñÃ~b<3ÌcÕ‘H£Ú¤n
-*”Z4(‹R ¡¢Uš¸fQEƒ„% •RLP€¶ÔlqºDb™™~ç¾7^€ªªÔý=¹ß;ï¾{ÎùÎ9wî{ºêk÷«k¢áÆ57wL›U_7{–ýÇHýI÷c༹³ “.ºzr9’BÙ'¦Á¤l'a$|Weƒ2í¬fË:„ÁÝi¼,ÛÈc²• Î-Ñ=G>¾öêk|þµï,ñÖW¼w&ùÖ¥®ƒÝüé“ú[É+;víüâïÉ_2Û›¼¸æbNùW¤Ÿ QÝ‹e°E¸¥!?e£õðï&×Ü}|u‘Âeûêvꮤ9%«ÈJÉΊ:ÌÎU÷&þ¢¸×»TU/Jþ 3‘ ƒ¶mþŠÜ&v0:A#ä i›*™PûØì-Râ"/›¿ÒEOK9q4ÈÞ)µ×Òû¬å´IïZÎâ²Ç¹Ã.9‹óÆ¡Ä7 ÷:床¬aòq ʵøq#n
-q(ÒNv`§p#k¤Г[‡ž^{Nß­Á¨&ìÆ[œï‚<bLP‘£'‰ÒɹyÊïùÙä…ä¼ñ]<›—lؼ79{_˜Ü¿XÙ˜*k wt݇¯]y)qµ§ö´¨½Böµ¯§»};°-ºÑ…two·È— }¼Í!EŽíÜ„AÄUbNÏ.È]c
-œZ|
-ËÀWñ%iLt°Æ4cºƒñmcÌr°<žsÐŒ…ÀŒE»€OHœ!õ«%Î’ú&‰Ðdžñ¼Äƒ$þ‘ÄÙ·I<˜¸2^—8G®³Kâ!¿-ñ09ÿ Ä#€Ç$¾_Îé$ì¶ý¼Hx@¦œyŠÇ[7É,Þ!f…ÂÍ«¾!&Š+*Ê Å7Ìøª§¬@À³­z+æ xÄÕ•¢ú‘yók‹ê9‹çT/™3Û#j¬¨X
-ÆÆ€å7ƒQ³®PC1 €|Á:Ñèk–š•¦ˆ˜áH¨.î7ëD“kÅc"Ö`Цˆ‹™Aáá},Zu7õEbQ±C,±¢q_ To­5¦¿!ncÄl3jÕ ež¹ñX<â«2ë¬x£…}3U8QO%^oY‘wRQqi¿öMQ¿wžÞ×[ј÷±ˆ¯ÎlôEV“¯3}q3"jšÃfT,~Ø# úâ.b šA7X+­˜Y÷ox¼#ZÛ`?+½aÒ¢6ƒ’¾°i´¢Q+ìÏÜâJÏ£¾x@T›Á [\QR>®¿¦¼¬¼¨¸¢tÊ8Ñä#‹aŸD„…"ÖÕG|áçÆ\åó›¢NRŒ7)¯1ÓçÇc˜iÆšL¤¯¸Â[.ŸW—‰†žé˜ŠTGñ$J® …VSÕDDU<hùD8¾2`E±TTXAÉó*+èlÅøˆÆš¦G<”›¾H fJ¼Q²³Ò¬÷áAHDãáp(bUc¨ÎŒí¥]_Ä߀ø‘ÐÑ]ÐqTWô>iµ»Þ•,Œ1ÓÖ±Á€lYØrË’,É–%PÁX`4;Úif¾<EòÊ1½÷º›ŽI% žCHH!9©' œ´“Þ““NÞŸ?³»:I¬ã}ïÿù¯¿yÿŽ¡ˆc,-gº°M§Àæ-ƒÍ2ÇU›NÔRcŸ1-«É4ÇYäRžŸ›pÄ´Æ¥â–:¤X9{ª—–禋2j¶¨Ùì{ÈÎh.û#„Êÿ·1õ&¹Ü ¦ÖIL–æVtû"¯±KQ»æ‡\0§Œ0›ž?X¬Á²»9jIU¦=ÉdÏÄþhº.\®PØV*´eœ·ÑqÎkòÊÊ=ð½œni,®k–zÝ…ÃÉÒ‘Ð}Öy3ù•ÕµIÙÓg™_xfD|JLÒ¾™W^œé‚!lÃw¥úœgk–ÅEá ázräTeÔ5,Sב>p,¡‚*ÏJ†/‡ŠoØÜš[
-­,Ï­È5×N)̪1%ƒõ”qc¯læÛÑnÓÈѨ™òÑÛéWæN”K¦H:vpÁ54v77¥¹¦á—X÷'ÛáwIŒ®j´0n½(xn†¶ãj›ºœž
-HöìTsI;Ò1‡ÛÄ–o»ãð´j.úþ䯕+§§§›x4sgÿ¿ý6NíP•Ýmì7ÇïÉý˜ï5 Ši6'-W^÷ ÷ö–ÿ¯8ðvÂ@&Øè† £ã=ŸÿªŸõAÀeª…gL~&PâçNù”hy³åÕ–C-[ÞzmÞáÄë/Ì’ŸÍÿ\I$'¶$Ö$Z›ëªlX}+öõ”e´°àíõxÿãC‰jøƒ«Àña|ŸÅ ø>‡+ñi\‡çêŸÀǨ–TGIJ1p©c’Bš!I†áG=08óp$æã(,ÀÑ8 q,á8p"NB‹þ,ÁRœŒS° §â4œŽ&,Ç
-4c%ZpVa5Z±k±Ž?C6`#ÎÄYØ„Í8[І­ Ä:Љmèâ¼÷`;vð§ÚNÎA?ÎÁ¹À †0Œó° çc7Fp.d
--£Sé4:šh9­ fZI-t­¢ÕÔJkh-­£õ´6Ò™tm¢Ít6m¡6ÚJíÔA´º¨›zh;í ^ÚI}ÔOçѹ4@ƒ4DÃtí¢ói7Ðt!½“.¢‹éÒh”tÊ“AcT "™4Nd‘M š¤=ä’G>¾FMÑ4í¥ÍÐ>þtÝO—Òet9]AWÒUt5]C×Òut=Ý@7ÒMt3ÝB·Òmt;ÝAwÒ]t7ÝCï¦{é>ºŸ é!z˜Ð#ô(=Fé=NOГô=MÏгô¦çg WðØó‹ã‚¯x7+'›+,9AæDüÖÁ˜ëйö˜ëÌxbÌ/–™8 ysÊ”w˜Ç#¿X?ÈÍÖøã;;Ócè i-¥é“1›gzu]®6eÔù‚QLÖ
-m"Ťsݺ–ˆ®ŽhkDWÍ xRú|O¹š/ÜDgàŠðYKËêúiáð<Þ$_EµìÀœžëáu•iÓßPlh4dÛMWì1ËØ®bÇÔÁ!ÓÊG2†åk|‰™~›ÁMÈfuÍåXÃíe6;RÙ®-Z-_' çs¢8…Ú1è ×…>ÕòPOL˜zù¶µíQÄë[“ƒš|ž
-µ%GÔÊSÄW›3á*Õ&
-Œ‹&2#yá«l§4µ•ìU­dfÊ’JQÛ¨Ë×`²W)ꌤ:•T‡î
-Íg®ú”D_¸jè—Áhn`[Œ­ë»«ÉðDݰ¼U†«Ï¥‡øKƒ{@KºJ™¦Ì[ʼ™7”Á¼"Ž:ê(»¢Z_ÒU¦‚ÐT0Ë”™JuÚš.õì IªM-SZD E3åÜdŒ2›.ÄZz”o)3¢=J,!ÄŒ‘2#]ªIפwDRéÞ˜±b¦/fœXs$,MÄ'ÜøÄp¬>¢Ã‘¢é‰X¢+f
-²Çu{4掙½ÜêrÛ—­ÍÌ¥Qn…•`¦¾</²ùè`>%“Ì´±:ÍR2¬3™ÈºÔ«<cn#'3x–p
-‚—¥•¤¯j4d«ùöŠ£Y½ÂgÚ+åÑ+]Ü©úÇI¶«J¶P%ÛU‘-”ÙlwÕéb…Oö„ÉIšŠô( fHê'ä‹ïHÀnêÙíU
-«x¯Â§ÙíxãÙñÊfMÏös<Ó[ñʪDÔ¯ì E†•"Ãj3PÑîª29]Åï®âKUüž@06 EßI jn—?Ýò§È?/3Æš#±XSÓ+ œ63ÐYÂ)Í«Ÿ¥ ’憫4¢Ã&µšÃ`iÃ)µ¢Yr5 šRÍWµ³´$øÉâ²–º*-/1\«CªéE ×¹ß\Øñ
-H‰ÜVy|M×þÖÞçÜ{cˆÕ„4nnbjˆ˜c¨Ô”P*4‚´"2„DR$©T‹¦†šR R<³ÒĬfjHs“G…×§„†ÆÓ{Ï[¹ÑÒß‹ßó÷Ûë·Ï½gïsÖ^û[ßúö¨Ùغmܘù‘ûаØÐ8ó5 ¶€ú8lj¼qÖê}!€¾9 ‹ŠŒ{¯[iv°PRÆÄL‹Œõ¼ Ôsäù»c#BÃóŸÖ¹ 8iì¯ãXpØ`˜8wà{±±ñ‰ wû]àû`@^Š™Z~x£¯y7641N ²k4væçãCc#Ljyð}g¾ˆ›09~oÚ“Ç€ïj@t›—z$oÐã`ð)Äp¨û—j;ö°¼ê—
-)ê‘*Tƒ¢¨ª
-ÏI¼ÐÞ 
-Åè°ðˆÈ1cÇEEÇÄŽŸ7qÒäø)S§%MŸ13yÖì”æÌ—š–þñüŒO|úÙÂE‹?ÏübÉÒeË¿\±rÕê5Y_­ÍÎY·þë ¹7å}³yËÖ¿mÛ¾cç®Ý{ö~»oÿwÏ?pðPÁá#G?qòÔ÷§Ïœ=w.^ºüÕ«×®þXd..á]*ž¯~x›Ñ×!µ¡@
-¥DZ,މ¢ÈXߨÐèj4›½]Œ½yn&·¦&aÒ™ê˜êšš\Mž¦¾¦Q¦ˆ&'ËÄS¡U2Ȉ,öó²ù9Ê~®NF£Ñæ§óùqþÓO8û¡§¤ióQ[§…h)Z/­>`e¾—¬©JNɼ’%ÜKêGO3/1¯5g˜Ós¼y¢y¤¹µÙûú}‡|5ß–âÞ/dµ¢ªSŽ ¨¾=®f,Ù˜‹y(ÇÜD*>EV!9pÀ|<À|Ž»ø °éxˆ"ü «±÷qeX‹opǰ£†…Ç)Dà8Nâ,¾ÇiœÁOˆÄœÃylÁüŒE¸Œ‹¸„±(Å|Œ(ŒC4bƒñÈÂLD&a2¦ S‘€[HD¦a:fböà+ÌâlÎF
-nãŸøWP‚ë(d½(ÆU˜± »q;°Gð! XgãÃ!¾ÆÙøà¬8ÕpB*²–¬#ëÊú²‘l.½dé#{Ê>/p¥Å«°¥btEtŔФŠ³ž1ǵªc„ÔÙVtäÝe+éýlÅç¬jþ*¼ªUUg[1¹’c•©­Žg–G–rËCËK™ågËMK±Ål¹j9k9ýœÜ_†í†<ÃCŽ!Û°ÖÆÆÊ¬ÁÖÿ™¦UýePCrå_cµ³ö/ÓÖä3ûÿçoå.™Ãê~>E&ÃIå“F–‰s{çní©=R·p†›U jËþV›š<ÿHœ«ü}Þ´—4~kÐÿÀ}…(É3ä÷ÒgR1
-ÕNrMâU÷ÒÊá8ÜÑŽO€,jB½)„ÇæhË´ÝÚYV
-7ñ–ðÃÅ‘#Žˆ¬¿È™*ËЇâ«d*[”­jcÕWU'«sÕ|Õ¢Oúý¼u€5Ùº×zÛjÑì5oÍGë®-Ô®ÂvslgL]®S7ÆÙí™Û>èÊx úÖœH¶(¶hF&–‘‰g½H´)Z*s/Ÿ±e±åp>rÙ61&ÛYöÛª¡Ê±ba;‡XO*µ¤ˆµ­Œ5ÑÊÁH6=›ìÉ™5·¹Q3jN^l˜y=ÉŸÞ¡|.ÑhЦJ§LZÍ–K;h7åÓA:Aç¯ôY„"L¢¥è("D$ók®˜'2D¦XÊè­ØòDkÄùºl-‡Êa2D®‘û”šŠ“â¥D(Ó•ãÊŒg/5CçÂÖSç¯KÐmÒÔ™ÙJuwt÷ô5ô~ú0}„~…>×àdp·k`[#’¹J}þ*5b•‹™ê
-”iu”Í2HJÁr“ÊÔÒA ~ 8ÍÙ ”¢PÆŠÆ2Q¸7ïé
-+¡­`«-ZÐJ+ÆÙ–uÛUI¤þ@B¼„
-Ú?,‚°â~´+Dã–3vÚmùÁxfî¹÷œ¹s¾ïœë{¦™™£tàA 2—™ •áú*¶œÉÇé¯ÈwMËð±éy‡¾oÒ<\‚
-<¿·€ò…U“ô;5y¢&›"µN#vdŸ²Þ¹I‡¢”Õs¯Ì•²Åœ¯Ü`V‡Zã1R¶6 Ø€’žSÊ„š@sÙ2%|#z¥©#Y=¯Ž.èL8;{DŸÚ[ÈŽdY‹Çt>¬Ò‰úœnÖLÈpí5ºyXçj¯‘NpȲTŽ­•V*9TŒn;¢™}¡ 3³šñ1ªª#úè—7¼ñXÞÚWÐ-à û
-×ÈØÃÅr~qdD3Þæ.œÒ<À”²Þ’Ñ-•ÎKú¥½…'µ²q×4œ4Ÿ.È赚]‘ Ó…œ¼è¤1fÀ¬>ªf‘â‹’nQŸSçJ/1Xþ’N¦OË«þ±Ìµ‡"cY©´¯ ÊúP@ÕfGšË.Rš>ýn>#åŸÖÄceA¬3]¶Ù·„mO
-GëjRÍÜÐëGTƒá‘šÇÑ¥ÃzRPuî7nGûIép?šá¡2zù+–„#lXP¥Ò=‚‰ ÞùûÓ#³[#æ°p¢‘.Sõd=Õwì02…ÆÐ¢gƒµ~o<öŠ>®.’>Ž”‘©>¤ t"å²lDy¹’!‡°£/î-Ôû9X%™Î¨¦Ó¢¡Y{¤qÚÐ,>Ò<~¼¨b:_©}ºu>òø´ gvn@ÏÿQ­ëqùd¥²‰ —¦
-‘ÙÒr R,­hš.ÅR)§J¹R±4[y¸xH•µT/-d‹ U®-ôÌŠ6HªÞSgCw˜
-Š[ý±« C¬f¶ûÊ0tÌ¡Åþ+@òü•k°‡x£“ÂÝôĽô¤ðqzB¸—&Ci¡š¾—F±»Ke1Œ7ÀºrSbÖ63,¹O$Óî'ø#ì:Ú!¢@2ó¹ØeÅ&+vIIQDɇOòçürù=…3¼Äau›(Œ‡`È)'ì
-‡‚/ŠMm)¸(B
-…ΉŠK•h£&W$ ÔÌÙ…ßÊ’ÄDÐšé °<ï ,ùý>ÇO™‹ÔÞ
-&†Å A ™Í­”ãl>Ÿ"úý!™¢k”ÚÞ§eBéG„£“«¡¼zþ•þ ÎÁÄFõÎŒOLuzEGª³vm5Ž”˜r¤R3359Æ}ÃP¥«(¥ÑÀÑ”:o눲_naëò(ÀÌ'GԘőâ„tšÃßùô­™î.,/Z Ï-÷ö%vö&;AæÌn—§ÉÓƒC‰A,9d†ŽB
-.+½£Õù¶¾˜³ýÁg’B“_œ¨n$»BN8MßdOÝÿÅþ6X_‡ ÛÑæBÜ&øÍ¦õuGk7¼
-§ml- 2dàîàlv $WCÙ=ŸÄ¯Ôß4};hôz,Ím߸|¶³R¹ÿ‡áöN§Ú>†XYk{|ó/]žÆÜë_ªn®{ÂŒ's!Þ)B¸ÆJ€¶Ìk ^ƒï1ôœ`¾D™fv3 VüL0~¦)àmfxÊ=Ø 2”þ&àw(ü(·ƒÍ®`°™íîš.!no“ÕåöØ…†ˆ ðOWŒ,9Z›N6̳‰%¡~Æ€` 4'GGǬ&‡f·;Á‚ïÔöøú^òñ™|×™ù/ûÕÅu…ÏîÌ®ŸPð+a 8Nc¼Ä6›6i±ÁÁØÄ8 ­wÇÞ‰×;fvmch ”F¨‰¢¶¤R•†¶R•4M…Z!DSUhÕ_©©ê#DHU‘
-¶û3wöØF­ÔJõøÌýæÎ¹çžÇwï­ñ¿q¶¿ö@­]«ÕžÓøb ­öA
-Wï¹ïœ¯ì­ªÛÓÐÓ’EœíHêÌŸ@–ý7öÏÜØ/hæ¶õ.só_Uì`¸·ƒJ¨Ã–sÒ—«ÿãlXÇ ±sñF¡v'U¡ò•ø„zQ幤óݯ–X††õ\žþ©oúvµ5‹Ê–­îŸ ¯k°|öµ ³g—Ö7tμÓÖZ_^P´º¾7¼õ†öø…µ·®¬[TÁì\R׬=yóËú[?º×¸çˆ»A[¼¾lY…Éþ=§.½öDåÏ|þ:ÕÊ›ï>þöAn¼ï͇fÍÖŸ.8ÝÑçUI'f눊/ãítñiÕŸù»T]þsJ.ÓmÕ/Q2°•âÇèÑà0õø®ÒQÿIŠC¾¤ýÖàýôOAíwðüô;[}«Ðî‚<é>ÓaÈnȈÙÄúW؆'èOÎý5p‘üþÀUÚ|„zûipOð$õh-ÔXA|êE;
-´–Ns×`ûkúiêÀ3¡Ý½½h{´b@»
-~ "Þ~ÿ¹¹#bhG"èß«ßzÑ"?»õÏRÚvèµÂû[¦_š»‰÷eújEwë—|¢]Œ÷#*n?Ç-1{1ÁñiaÙÆþe‹ø'27ùØóíva¿²E;[èYà³BøÔÿÁ‡Oðüühb)xoîŠä‰è=JE+ææ ³5pqâÙ“ÀÖ¹ßéߢNíjy†‚/QýëüMø\k¡õUÁ:2
-Ši«òçsOø¥AŒïCÛ¬ÿ™ª¡»Ò‰\¿ÌõrÅù)ºHÛPÛ~®_!D
-©ÂwŸÂdûš]Œ[©ï…}Tä{]a?ð[
-kÀçÖ©p
-¯p<f¯ðó~.öýQaß1@±ÿ~…u
-ùÑôïUX§‡üaÁè/ô?§°Nkü/
-.D©ÿ¼Â:=ìW0æ÷õßTØG«ô¯( ;ú·Öh£þ}…aS¿¬p€*‹Òƒ:… èí
-Rs°Aá"ªîW¸X?œR¸„†Kj.¥XÉ3
-/*ùuÉG
-/¦}ËÏ
-.æ\U–+Œ\U®\‚þ%•;Öi}¥)¸”c©|Yaø_ùªàĄ̊Êß(¬ÓºÊ—±ªr…a§Ê«œs^µWaä¼ÊÍyûSõœÂð§ê›‚—¢¿¢ê]…uj«rí/cýêå
-C¿Úµ_ÅúÕ»†~õ¨àæ@õ«
-ƒÕ¯ ¾—ý©~_aøSíÖeë×”( ýš¥‚W3j:jú7ŠþÓ
-³þ Æ…’çš³
-ÃÏšw‹ÿ5Ÿ(ŒþÚ
-#,ä!ÌÖ¦ÑÉGøÁ³¦Ä_7w–ŒŠHçÐ}~Š&$Î$tØšg?‰øî^1ÖˆçÉ"O× Y™ÿWFîß“é 4ÃÇÔ,׆k!3¾1/ÿ§«5ß—AA¶ìa ž× ¿zŒèG;">Çd,ãÝÐŒ¥ã³Õ°d/ú|jÇ3GJÙó|ÆÈˆôD€â2&š¶”̲ÓñåADnŠ÷QY‡ìUB’lvH$í¹Æ²2ʳXh#RÕ&jgÚd_³åm*]MKùâb}@ÕU£&ä#óºvIEð…+Ä»ÆÉHD*WÖB2 c×ã1™ËÏ·Ù¶$N—-Qño2‡ÿ™z¤„[ɬüæòÍ”‘œÇ •m}<ï˜è
-w¦Ä‹°ØÊ­rhA¶çÃÞ{×Ë!™Á­»:LÉ®ËÎ}¯èsýÜ÷ógöªÓ®vK–lÉR\ÖBf…Z²zâ’ Cª˜T±›bÙ­¨¬©t 8Gœ K­
-!ÙÌÌäÞ̃¹¹ždj—ç¼3)%ëtBØuûÊ©_ ÷õÂAÏÄʲǣ”â]\ÅåžoÉy‘eÖê8ævÏBKÎ[K"´sÖ·£*g¥÷&w†ˆì†¼ÓÙ²nBjÅÆÕî7¤²æe€YÃk))3ñÈC‚<oBr.§àÓFüØ]‹Zñd3%$+p ¬?†YÖâž¿˜ùü”¤ËÜqu=ë¬ýégÉݧœtÏÉ[T"ÊÌÓ‡ú bgî†t
-«{ÐÓ'Ìê–Áýüµ¸wÎݰ¤ ×vé¤ET,28o7ÈTÐë©z:òå²a:‹“ùœ$™ZYвª½ýxZ¸êÍÉù™Ì:ß&TœöðóXÃê$‰ÈjM*†¸ß¾¦TŠÈ\Ú£fã53©ÖçPúät眿Of2“”S¨nXí ¦ÄS>Få1åÌu÷Ïaµ³-”/ï\ጙYV¦”ͅ拪Ë‘Õ0!ÙÈœn¶Dq‡
-UUn¦LÙ ç³bþÌ™/žIY­|JdÖcR¬¥îÈÎþ艧÷éyµpë”ûuãîañh\2kÁ¾»Oß½æ†â¢»Çº»´7/Ÿ—Ñy;Pö×üš´¶“ÅÛÛOÓ;eнû¯ì{SRÿQ©fö7 ÷½‘ÑôNÜÒ^%ÐQUgø»/“ÌKdÞ ¸A=¬MB²QŠH &‚B2±!“Î0‰¸„EY
-N­PKqpíÂä ‰²im-]¡‚],–rÚSq[*çxzŽô¿÷½—ÔA““÷ß÷þåþÿÿíòʺDÈõ‰Ýu{t½b£ÛœuÿGoAfÄ]-†¾È¢h|Ü%lï{r欢w1_Œ55êjC¯3ð¢÷íÉ”ì3zX½Qåùl»þʘ:Ïé›òôœä¹ÚlœF4Ç¢]»÷9zŒ©Ð#¤U‹¬¾Z›'VÝË×uפmÔË}w0'¿%Æ[¬Fº=<‚
-z$, úÏûf>&#î6ybž½ãé}<ýÙD6:è9™þn£/·EÝ“òè[riö"þM‰¥†½íˆ­Æf¥çY-jZß|j Úànç6ꆙ.²Óf|w¶Ù®©«š¸q½ôvRn“M<gE« hþ­5¢´I<õù¯É°lŽÈ–Vç3âj™¡g]OÏæ<eÆÝ¦š¨ë >£ºq;ïvúŒâº!òÿ¹=žmUÛ'*À­BW=r—ÇÔzçlµ‘KzåÖ§`OO7ç’š·^—b+™ë
-¾Þµ!º“>Öˆ›‡Ë˜VõháÙÚÔ3û¶öpøDmXa|Ó}å5²øF{³ZhkN.cn³õò'ïS{’îIý^YkT1aœôn¡¡/ojÁåT‹Jåª5¢¨FTÉ(W“¨a_»"¯ô™Þô¼Wô èÜm3bÕ%zß}Fæéßn”ÿ\F‰V²Z‘zT¸{EÅ
-˜÷Q·ÐLŸ ÌIË-ðîž8ìkµá·°P÷ò•~ðÄÔý®t«‘Çú­ôç¹!þøê·†/—?.Ñat’ÍË>Ò÷hëÅÁ«¢Þßõ\oŠKF_®Yâ}qq›´¥”õD{‰äðüˆ‡·7)KŸJù)_‹Q®r±Š‡W§ü†ˆ¡fªñò]É1׸?ñIOψ–¸¤\/öDã³ÿ
-‹j™n™j)²äZò-vË4‹Ã2%)Wå›&ÖŸ8ÎÅ¥G”º4n?ê”îM6¨âá‰R;DEm$úø<K?›þkEŽ/GLêëÍÑë<ßëÞÿ«ä¶ñ» <„«ý>1`,HD¬‘Lµ²R©f@Ò‘L Ä †‚!ÈÂP C6†## Ò^#qFa4nÆ-TËo£Ùv ÆR_¸ƒêã8šu'`"Mº“i¾Í¥Y7Ÿ¦ÜL؆é˜;MÎ…(B1J(¦fQ~Þ…»é¼gÓ\>‡l›‹{1l›Ot9õÌ
-ºwÝ…X„P'“K¨&óž\'f_7$ïÔ“ÄíàÛä Ÿ¨ŽÍTñýä£VòÆ*<ŒGð(CVc ÖbÇX ؈Mø6c žD
-#'òci•AäáÄGî°'wd(ªWÏW½J¨øˆµ‡IËs‚$ü=žê&A­HùÿðR¦rœ`©ñzðvõ5Ž<¥Ý­åÈCƒ”#I–uuxÔ„dÓµ‘Ê~¾´lE#ì>Â>ŒX/VvVä§‹$%­+Wù>‰Üfàž¬?4\â®ÅÂz5»²–ïAmâ¤,54\Ñ‘ìš?‰bgºæ·˜¢ùey:§ùÓŒÕü<¼Æh~:[ɦù) ¥ašŸ¼—& …Ÿ¤èRÐ<:3q2ER?8Y›ˆ©„°ó´ ;åÇ_›°ç„töŒæÏ"ð”æÏWgöcÀ)uRõRØ*°•j£ÂJ4*‘ =©:„Àš7,ÍŸÂùÒÌÙ
-IN'ÑøºRup
-INV'”z7JÒ¬“$ž4IOÆ*Äi(.¡Sel0©26ktDØÅ²
-­tdiɦbâJø«oZ°¾´dÙ¨’ÅÅ_LÖRÙ+Ô2ÚaPâ*Añy?v ´Ÿÿs²÷ÿJé9œ"c ôf&n.`ºMVŒt(°'bkE‰:é], Œ+¸µ#7ð(;màb”®£®#HŠ…,Åæ‡JIÔY+Jïb\•
- s÷3l`rÍØÁôÞ5cƒCwÂe— l P%e—ââÆb
-H‰ÜVy\•e~Îû~*\ôzEÀµ,ÔÌ\H³Ü0›Tb 0AÊ\1÷ÉI45œÒ
-§!M3-´r#—‹“Ë0V&¹D9—ož{µÑ~ƒóóïyÏïý¾ûmç¼çyžsÞ à‹©Ðèß/¢M»ä¾£¦óÎ)ÎÁ1IÑÉÎãæ @Úæõ˜I)v3ä«€-ðz0>ydÒ¥Î:Ò§‘=21=>0õ½| öNÀoMB\tlñàn @ÐPúëÀµ ÛI^çò:0!)%-2&¢×Û}$q\L´mˆ¯7Ð<‡1HŠNK6¦Þ7h™Ê÷íc£“ââvl9ÄëÅ@ƒCÉã&¦|4ó×ëÀ3±€ê”<!.¹wEÎy ÷jÀgD_––0¹öf{zÈ»y–rÄ«ÅT¦—aš¦RŸiÜ1žï×·ºÂ~C™;«Ú‹Í,ßò¶Üz¬oNýè­;¼â/ äôºýš(þ8øP¦—ÍÛç¾ûð­Q³VíëøÕ}¨žý<Ò°‘½±£I`Ó àfÍ[´lÕºMhÛví}¬ÃãO„uìÔùÉ.Ou}º[÷=ßéÕûÙ>Ï=ß·_ÿ#½0øÅ?½4dè°Èá#¢¢ñrLl\üÈ„Q£Ç$&—<~ÂÄ”ÔI¯¤¥gL~uJfÖÔì×^Ÿ6}ÆÌY9oÌž3wÞü¹ ß\´xÉÒeËWüù­•«V¯Y».o}þÛ
-6nzgó–­ïnûË{ïoßñÁ‡íüëÇ+þd×îO÷ìýlßçû|ñeÉÁC_}o9zìxé·'Nž:í,;Ã, UƒÇpbh ™°¤­DH´¤ÉBµOíW§í~öö†v‡=ÈjïhïaßÜØÑ8È¡^ŽšŽÚŽކŽŽ^Ž(G\Ó—Õ eYn` ý ”(ŸÏè§Ô^Çîo°Û=~ÂþËOýÿø‰¥¹!–e¬|k¸•mu·ü€ªZÀ™Õ7É93ýÌδ3µËF—¥;—8×9g;gÎçxçgg艟j›ÅŠ{ÜÁjåÍ)C¼Qý¸^ͽÍÈÃ4LÇU,ÁYÌÀ<ÌÆJlÄzÔ¨Àëx?àGÌÅRÌÂÏ8ï±
-›ð.á2Öa öc¶âeÄ`bñâð9à¾D ââñ ¾Â×x#q¹8ŠÃ8‚\@9r0£0IHÄX¬Á8ŒG2&`"R‘‚Ix瑆 ¤c2¦àU|ˆµÈ"›S‘àŸ(ÂqœÁ œd¿(C)œØ°ïc;öâ5ìÆL|Š|vó˜ìÑC(îcÇ©FÚÐ蚺¶öÓëÝZ·ÕOènºçZiv/j©|¹rLejeFå«•Y·”リS†öòD¬ÃˆMt+z+âmU…Ü‹®*£*GW&{"fº5榶:¹®¹®º~vU¸.».ºÎºÊ\NW©ë«ä¶þ8ïAÞïyoö.ð^ïç½Î£F7kðÌßÛLÐÍy·!Iiȳ½Ú§5îþ¥gè[öÿ¯_w–Ô°ÉÍœ÷Ô{áOnËŸUݬ
-s&0¾ÇKm´®˜™Ô9¬+ê¨û|{Xwü*öî6é=ê,Q‡gV?^ ¾ƒ˜ù;DÿméOìOãó+ÀSˆHdHMb7Dù­+x–ø}„]Ò6⸅خã÷$Кoâ–EÖrˆÊ7ÜɆ“§Rü†GA®fóÖ4E5°“•m#{¬ßøæ zb«WE¯aõqÃÚÊ=¡7×I^?E¥>d9¬løáŒ .
-…ØÐK=8ÐaèN?CÈññÕEÖ2k%«¸ë8‚^‡q-ãÈv*Ù\
-§êé‰Cý,Ä'dï ûK€¨Fzºj-²J¬«¨‰ºŒþ<ߊgf¹ŒXÄUœ“Ñì7Ô,µV—šó­–V‘õ3¯xŒ«G/ f´ÑÔQ61}‹©£Ú6”Hé"ýd“lS©Iê¨óôq#Àô«:YuÍÚh}l±*X¡šyùà~fàKõÔgŒÐ ­Ð OÒÂc83HdViäl «hY.$²»©ÿRñ‘Vò8WºZÊå’j¢ªêûU¬£–n”ÚÒ]窶Z°|­H+Ó:ЇÅ'-Ñ–¬=Ž'hÐÅc݉ÅsDØ[«&…’EË&[Óhs‰ä",c…çy²-àj¶°Vße•qUÅÄn+õþÎ:-geÿH=]£¹hUÜ ï—ROü¥¾´—'‰Rvßy‰8^’eŠÌ“å’/Do«Êv)–sR¥üUˆ
-S*^ÍUÔ)uQ]R—Ù£qGè­è =G/Ö›ôý«¡˜yg£‹ñ¢1ÇØlš0ÃÌQ毮ÿÚYeV«*·¬QV±p3àC¥Õ'nkNv[ 5Ú™ŽèL,žEjc
-¹¦QÁªƒzZõP=U/5@ SÑ*I¥âæ«Íê[õ wÎ`ZO=W¯ÒºPŸ7| £¹ÑÚÈ2ÊÍÞæló}ó¢W¯å^y^_ØBlá¶t[†·¿wŸN>[|.Õb²ûÇ]às(ÔóõEv…)슑ò–|arÔ¬Á.œAÚ_ÕÕùX *0O&áˆ~E_S‡Õ—è*0ÝðÅR•9R¨Vòû!(—6T{A{|{øzÕN2‰r´º r¥ VH$‹ƒJúIÅâ.pœuWRõ:¿­+»1JO4>0¦™í´%ZÕw}§rTšæ«}²S†âˆº ã%ƒœíEˆ\–Õëß|Wl×ß;Ÿ}vâøÎ¿Çᜳ`;q~'7rÄvˆ$$™M 8 Ð@ÉF‹‰.l ˜Ãh×Ú±eh?X§‰3i+Ã&-“ؤMê&m“Ú¤õªbÓ²Ÿd•Ö&Ù÷.$‚MÚKüÞçûãÞû¾ï»÷†þ7´ã»ÿ=r~cùMœóG8ó0Hd(!ߣ&0ÓNÂFK¦’18OÒ+2¿Cp„ÙÎ<G 3ÿú~±¶èM”‹ú©·5756ÔÇêj£‘ð¦šR((V„ UþJ_E¹×ãv9vž³•YKK,fÖdd 4$š»s‚*åTƒ$öôÔj´8†Œ±'9U@V÷Ó:ªÓÕ„§5Ô<ô_šÊª¦²® œ ¹6*¤DA}7)
-EØ3Aü…¤˜Ô÷ëØ é„‰@
-–„%ˆÔnñXº·€¨îTG"¬­R{ÅdJM‹IÍ•¥Æ¨»2©¤/ÈÖFUHLˆã*»T[DW! }Õ˜PMú2Âam;dV(Dçó—ŠÏEJˆÆöfTz,«­ÁGÔmbRÝvú}om´ßʨæDÈPæé]™)¤g’ɬ¶š=‘¹ð¤ºÎ§¼‡Ìç/êõ̓ҀÖg³8im´o0@«ÅÔ%AÛÆ`FßN
-Þ©ñ´m®nø ˜Ò8¹#‚j»ÄÉü‘«"¯’ÁS۽ʕ÷HoJÈeÄ€Úé³cÉÊ‚“äOÍ¥!ý´¤6ZàøUOÊlA©õIpp]¦#]]Chõš«A³HLcŠ¨Â„€–dD•
-µkÝÁv’ŸhG5lY@Fÿåò\‡&ĉB~¿Ó9qáÏOsÆsŒ!n‘hPK—õ”CùV#5Ö2Å”ÀТe[tº¥6zBíq‚Ú‡.#»2øP¶#†.´(Ï2Ž„:3Y¥2î»M”X$«R9M2¿&q k’™5Éúã9Óù-ýúæRYiý߯¹©ÉÜÿG|pUŽå“
-&”ß•‘Æò³>)—¿”ÅÐtc)æóÝ¢ÐÏåÇŠ+3ã¢À‰ùB__þX*·¶¥âÊü¬OU.e'ª6­zCu$2´Ê®"ÊG#êÛ-ö ìÉ©|îqàsÚuŠPšøÉ#úábW1aïmb4ý
-¿uÁ'µB¹Ê­àq‡‹Up^„cº¼§’fËMbE›(Ö–Ñ'Yî;„ñk \›‘`Æ
-zVÒŠ Yµ†*9Þ* E°¡ˆq»ý”NQ
-îL;s¡5íB´6¢Ñ!Z>j³Zo/B_È1T´ö…œã>‚;T´ô)¨V {J†„ 2¶¨‰u^u€£KBÅ÷~©ë6è õ,©´¥7¶P–C YÀñÿÊØH;W5Õ»½‰5«ÊwâÍ)§3Õ7î)š‹Ç׿½…‚/ÓÅLõ6x³ýe¸¥»Önµs=7x¸ç€"\wÀyÔòð›`š eHýº› énf§¤40;/‰Ý5X
-.8ŸkÉ…Óqõ•Ÿ¼©íÒnh?¾ñ£Yèû`ú“É?9vôãcëZ®nÛ®½ó¡vEÛqÿwàø#t\yæ¤vçƒßjŸ:‰KoMo‚ ¶»ñ*vcŒÊRÿP… +T…õf‹ôÇH³¡µyÕF³­È£X`Ãqf󍀿'ØÍ2·Zäì³`ÌdG¨ºÕ/ÙE‘×»Ox6sWÈFUà»ó•6î„Ñ»Î.Í!Jð$‘q>gÏGFŒÍ8•y¼(4–·;FõHÃéà×$iÖI¥“iº‚ 7Dlf i¼¥+êÆ¨zCv sn_û1 êñL@‚ Q(PH_.‹Ú×b& ÎgBÌ"Ûéÿð—Ý£úìZmQz“íšF½i¬LuÔ”?M6†å
-ܱ†<ìÿ™æÂ“ëö¡¼¶cä§OÒZk®Ê(Яh_ïBR¡`Q|•3gZê]îò=Á=±½°'OTá;nþÝ›ƒ 5?惧sЃ¦L‘aF†s2Lá%Áa ¾Kíƒ}ƽ޽Aã05 ;ŒƒACšË3>WƒPEUXm¶Wcq1‹ÇÁǸsõñ˜Íj0)‰Yènª•ŒŠ‰’³2À’”ø+\Žfá&åGYàÈåÖ*Ò)³¦ÃõŒrØÍù$™©ŽæHz¬Ìù(‰yk>?R8¨rTȇ^¡SIÊgÕT%žðÕmÉ@²-ÉpTØdW~ž_ÜÈ\õÞDל,ëùRßµÈG6ì2žÅn¶Í•ôS=Ê”H{X°=0}æêRI7vF(•©‰8]¬™ §#á0›©£j\Ñ10§Lcq*cËùw„ýKò_"“·B#º  “¹ŒÕŒC4(¡HÔ¤0Ùjzas‹$
-qµ:MU”Y Å ÅBlñ†öc ÇM2fˆ³#©iØ3_g1‡Àa(_Ùs¦ ¡ðU1çåøN*ÿëá=¾Uy À:^Æ—ÐΧNlé—Ò/ñÙ 4{^VžíãGÞ –VX›ªìµî®·«] _ÙTsæÀЉi³K6Þú¸Û±`Nâ¬Âþ½ÑE›ôãÅÅ>óľÄ+o.[ûPN¶¡Û—5©ޤeûûLù6Uâü0®Ÿ£r‘[ýüÚL±Æ!;ıñ®!.èŒwuõ„1¢êaý°qAùެü4G~AfZfzgZnÞìÎܲ¾Ng÷üT#¥35'kVgNá¶Î¢îùyyCYGV–C7ŒŸd`.(ÈÏËrdzBª³ü)qT¥´TÃYT”››cŸ*lÉ-"§±BDÊ´BWyK™(kXºõÉÛgªôKëÓ?Þ²…Ë>þI¬\Ý,߇lþ
-j(s´3¹ÞãŸÃóÄ÷騖ZYiK{r]Wu
-"×yŽ2‡zÍ!äîÒM\éfbùK33ïÖó ›.&·iî.¶¬ÉÓ\<W•_x¦Y„º2“‹Ëžº‰DGɪUµ·®.ª2çèÆÄø 3ŠëòoÝêt,˜«gµÚo戼úìÔ½½}Aéʼng—.Î@Ò2ÓÓçè6±d÷ÞçLäÐHZ¶A+DîPnÝÇzN^ömM«£Ü’¿=M¶g6_ôMì(L³5ã1‰õeÆÉöÌD>‘½
-£{ǬþÛ¿1ÃêRY⣳ª¾ªRD§¶RZgøÈ%Þ¤#¬T÷QÆ?ý“j) ¢} ϧ¡ïׯEZÄ-í!G!{!ƒé³KêK[Ø|YúœÕZé1ãPì—úRõ+Ô Éyõ7©GŸKýÀ}òYy•ÕFc7Ðß »Çl›it»ä8|o–-ÆÜú:Ú©Ç>1ªh½~ŒÛK”ƒ~¾tH9âxöB» ­_£Ø5ø~N;Aàg¹¶ˆÚѶ¢í
-zrˆ@‘Mb忇µÀ’Ý…$›î¾M
-«´Bµø H(ýѪ­=ÕVkÕöœjÅŸ­íiO-é;óöíO¨è9ìžy;oæÎÜ{¿ûÝ;!ÒS %@çëÈ@½ã“°M³o&Þ‚´’Û1&­m£ïÛJó×v:é~’•éåòÑ~%Hˆà û½8åÚAøNDG¬+0Ãm¿ˆæsÿ‰÷¹;ÛÞ©B¬Ö•Âd¥Š'BC=-d /y1*u’äÍ
-P„t¦|ÐB9«“<º6 !éÈtl¼äfžÄñÝ•`ÎÎE&ÅiŒÐ•9eؾŒ0hŸ°MZÙÆ‘)q×"õy-š£™«í¸·È!ʳ!Ò0œßé¹PŠ›ÄĆœéÂ7å2b[$û­‘V³-¡š!F'óÒÊ ôdŸ¦œò±‰gšžiè+þ-'¤#¥œ"°gðù­¸Ë4lM:G>ÿ…U¸–cG̵¥óÙ—LžŠ¤FV‘ݤ‘³Ïô_-2s þ>K¨¾G–²j("ø8¯ª–cËmw¢d>~Óh-h0ˆ~µ9làxÐo–þŒPõ$а1 “W’I_…$*bÕ6o$¬Ú{rût¤å·˜´A$=Aª
- úe&i¤hJ„¬%)AòG ÇRƒÜÇL‡ŒÏ5©Ì)öÌåIÇ2QÚÑDïú%'I¯fyÆ
-ãÍÑ £iïíSp9~b2gU@¢¨‘XÒY#›’W¢¦·-¡äÔÝ^‰Õ å¾zybìjÙ/(yÄa²
-‰éÏÂŽ½ûSÖš Ý£ûå s`™-”ûÓþ»Ç»g¸ºorÏÅvVÆ<V.'e U¼*ãÚWáx„8“Ÿâòk~V€>ý
-è‘Á0=SC¡Ša ‡:Œ„R£a Œ…q0 ÄÃ'àø$\ `""ffÐëàzDßTôÂ4̨3àS˜O+0‹ÎÄŒzæÒÙ0> sáF˜>Ôð3xW«Æ{Y ÞÒ>‡µÕÌÈ‹0ûó[Þ2ø<ÞÜ–cE¾ê02oÁêîV¸ n‡/ÀJ¼®¦ê»‘"¿‰2lÖa5Ù‚h£ä‹h(EOâjúhZãN¸ 6Cºàn¸¶@7l…{al‡/ÁØ »à>ø2ì†|¾
-{`/| ¾ÎØ߀ýÌ÷Ã8ÈÜð
-§]­±®öÐ ×ÒæV÷üX$\îF¢áH0¿5„Í!MáX$kFBáHø\*0XæÊ÷•°Ä|VTÍVWwU+Ó«—U+«¼¬ÇÅ,ÏD£‡íµº±Sî´Â“°ë·Â×awÉò”a÷_ËÅ»,…woúµUa3nî6]óÌ¥æ*Ó5Ô4Ìi¦ëuó¼Ùoºº ‹)çá<SÎÀ¦ì†ÝL‰Cœ)R¦¨P dzÉê’çKÜ»zX­•oìêeµýg­|ýBk¶\ï|šÛ¥w>òò8ÑT34Vÿ›žö4‚-FH¼Wfû†è:ÔÔà6ÊUߥC¤ilµó|… Ú» Ú ÚÙíÑ­Jgƒ” #{©]OíjÞ*£§û&µQj×ùŠë´—ê´gë´gê´§ê´cuZÕpe&‚OS¦R;‘·ìµ;©-¤Vóvi‰.í®.mm—¶² ×± k£¶…Ú
-Ÿ¦×Œ¬Uc¬S0¦ Q5ˆ=Ù&Á6R[Cm‘ÏçI\ô$6xížDÈ“¸Ý“¸Í“¸Õ“¸Ås­zêUÇ«cÕÑj©ª«%ê0µH-T‡¨ƒTUÍWÝ*²ÖÑá®…ÿc´|^Ú¢8>³ÑFMS­I bâB/Á¼´ ”uñнXãa·U“MHØ^5QèE{0Å’Z…"^zHR=̪…$ÐÖÀ¿!Çþ…^í{³Q#ZéÀæå}?_æ=v~°Šש!NÒÄHEÄŸ¸Z£=Ï_ˆNU§¢ß ƬObF­‹ÌˆÇ1Cø§_š.¥,¡lÖ(™5kô楰èŸ4ë„ÒRi+Œñ¬´eYÄâæ¡Oóñ2kî³ÒÍß3Ë“;µN)AzòÈ~Í/å
-H‰ì—ÛŽä8Æí8q’:uωYØBËAH «/€V<â¸åi¸äAàö† ØÝÙÞžž>T¥rð;I%©*gÔaª§ úJ?Y®Äç|þü7Jª
-|¾ßFï@£Àw Qà;Ð(ðhø4
-|¾ßFï@£Àw Qà;Ð(ðhø4
-|¾ßFï@£Àw Qà;Ð(ðhø4
-|¾ßFï@£Àw Qà;Ð(ðhø4
-|¾ßFï@£Àw Qà;Ð(ðhø4
-|¾ßFï@£Àw Qà;Ð(ðhø4
-|¾ßFï@£Àw Qà;Ð(ðhø4
-|¾ßFï@£Àw Qà;Ð(ðhø4
-|¾ßFï@£Àw Qà;Ð(ðhø4
-|¾ßFï@£Àw ÑGFG•æT,ä)¼Í¨ä~U¸VlšŒŸL™Oî×hÔÕq Èô”Y°}Í„Žœ¸nw;ãšV|ðÑGæãøè}MÔúÙÄñ‡c¶2ReÔGG»pktÌ'FtêÄFÛ?Ÿ=ŠªPè‰ë
-&Ø\V&’J´àº 51kT‘5É+™…Éš/Ö2¼Uñ:H,,miò$Û®wzÕ£Vkƒ\®ÕÙ­zz+Ïת. êÂÆ è²ÍÅ^†¬Þª†KýòR}ïR¾°©Í¼üV|úüä’¼ø.xv_ñù»$½
-ç7ÁÒÅâ‚=ã28¿b«ëpqÎïÂdñMÈïÂÔÅü]pöŽ®SSþëŸ×lnZÙ#^^òÕ%[] }µvdt±—²ÅMdÇѤ7lf‰m{‰–öo÷¤É‚™}e÷+Ÿ4µººÍ+S±-®Ø™Y—~0f]>ZöØ´c>C<3ÜDén)ãœE9 ‹ŒÙ<‰rçŠg:Í¢§yôtKY¼Êž’=yYò•P©*)C)˜ŽfºÔZ„Š2E8Í Õ1ULWDÒD66,Ùão*ÿžs¸ëHñ±6 "ÙLR}²Ò hž“\„gá|άkÓ†1Õ‹ÞD­}®Ö½•®Öú¬N—G®yÜÎòB}ÿzõF~Ú"~P§¯¾©~øxu¡¬•¾¥OŒYŸc³Û`á \Ö¦p„1µÚ׌‹ÝÒù-[˜Ie,ÎhÔÏqˆñµÆò:ïk0öG¿ýª·™÷´~ìJ“zQÈ`p¦ã.¯ãÞGº—«ý¶ÀAzP«{b&P»àaµUŸt¦ë0QM܃¬Ûoz)kr,°>JÂ’rë£:¶>ZÅ[•f2ÌJ±)Ê Oóý¬úé¯Ä³WÖ#ehÌRÓÚAóRͪ
-¨Š¨4i mtlãW?þ¦òøè‰)©6z˜hIí±ÎR•ê¨R|+g[‘neZЙ½Éš4\‚å4µ4··z4ùŒÌÐ.²\nÔ
-«’Tá,/Øšœ[““Ë\/MPŠDÈXˆ°"qE›jnQ‘Miì6B5ÛªùV/lÚ çyGûd¶{;+ü¸÷Q°*`"Ž ‚™¸„(¯˜é˜A–ÕLȤÞEë_ûT訟Q=»¢ÞáîvTdÊ;©h%WÇ@â½rý»c#î2V~X¸)ã,Ù;§I‡ÏI<X Yÿ ‡ŸÍ|ZmR“Ÿµ›mÎßÁú†d(´&ªûqÖ ÍsÊ3M7JlH±¦Õf››uñõ›ê« ¦êw_¨_n´*N•fZZ‡ÚdT`¯SÛ«Õão*’Ù­Cë£Òœð6ÖÌT´®¸ñÑ5{žée®ÒR&¢ŠuÅu
-•XŒ§îùÓ`ëÖ%MjÝŽwuK9Ü®iã^îÖZÒÁ~N 1Ø}¥˜Ü²Œ‰™¯ ZF–ÂÆå5õ_~4ÁxWþ€F›À¨ëOï*˜ÝPaâ@[Þx »æ‡mŠ{ô«¹ýT»¯UÊ´G${sÎîØJ“WvnŽfnѵ†l“5«Œf¢È«²Øl«w·Õ?¾”×7òó×ê‹ß«å™JI­h´w‘Á½Ö (øèéá,+#!iÈKН/Ö¹¾ýñ/®“盂›xtœÛH´äZ&Zpøõu› É“ÑPJ8ûíåÎÇ÷Ø0 ‹×jµÖg6U«[u~+ O Wòŵxv'ždbYV©®"&LÔBÝómŒöÓ*ì蟗‘»¼ñQjZêý¦ ¦•¨ï@ÞÃG‡åEäÜpˆ"vtì­]×Üʺ¯’õUL ™¨*vPr%K“?xÛùhszÚ¶öÙ¼jLÔ@S§æA°ådë -3YæD–²(òmqs]]^Ê¿ý]òDýáêõoíѹ-ꔪ€ËpnO¿ïxðѳ 8 ™ÔænTU4ûË_o¾ü÷ÕŸþ|ñ“×™N3Y_léÌlã@õ–ÞESæFÕ¥Ö?ÈÈ=—ØLk%ë<ÅÃÚ*¯#]^ßzöz—!¼Éùtb´1Ñ\ÎMàdZ£ŠF}Îi7r· µÁ÷¡#‰ÜíE•ý,ÐÀþÃ~¹ÿHu–qü½žË\Ø]XØ„
-®ÈEcjS%&Mk5ú‹©‰ÖjM4&¦1iLˆ?Ô6é/Ƥ¿˜ÿ«¶¤€”‚Ô(®,ÐB±$]ÁìeæÌÌ9ïíñygfggwgX–íl>9™=çÌ;çò¼Ÿçûz4ïæÑ®éN(Þyÿ\×Þ:sLܱ›4D‹‡Ú%=ï߯“…p¶Kº¹ZmO°ÎBMH¹jL+TR 51©³YRÖ?©÷í³;î¶íp¿þûÜNËDS¥aõìßEvéK=Úéyt™Q2¨*.#Ȭ™¼°wâÅWw>tåÉgÓÕRYÔ†iXÖX?qêD£ Ð%4<Ú°ŽY0íR˜UéÜïÎs´)®yT° ð°×'𺀻Üo·<êW®AóÚ¯¹;ÇKÂñgóèLíbìzƒh Ó….n¸Æø Z¿ÒÚ©eç0:ïª\dçÈÛ-ï^?û¶Ý¬FS¢GmÐL¨ˆ®Ÿ™ ÿE4+ ±¥œT#Vå&¥JL›4KÒGérÙráõù©O»gžµÛ¶[”¨Æýcd‘UÄÒèÎOª»ŸžG—%Y†" ” +§,ûïè›W~÷‡ËÛLŸúiºy‹²TËØç¸$
-Ü©Q÷§vtâ
-,>j)óM•ý—yiŸ;sÎÅy·y„|üc0¼BAóä¤íÏAè€e¥Ÿº*²i1qYþçœ<uLþè ñíGI–9*ñ'êeΔ‘/Mÿ¶ì~ w=.3†&6NTð¾$?˜°¨
-<rŠ&s¸üÒDªRUü³:ü5´6ýÞÍÈv#óÖ0kx[½vá&<êd‡1AfuäýõèL¼éyt°“æ]€i†Q
-„
-Ç$ŠX Á÷I”¦4vÔ•Y6é=ªK¢tUV&äÙŠ gÙÏv“]»\M[ž³­^ìk¨õήÛî?lô<z“`m¡óL}уå…ÿ6÷@I‰+”ò«K¼¸0åMsÆH.¨1DÇE­A]¸”þvŸ°Ý>ô5[X9Ûýl:i(–Ŷ•/Ûi
-R|@|±{»F»ö¸%6JøoáÖ0ÃBgÁõæD€…E.^$¯¼BŽ%iJ6n$[·ºáu¤¿Ÿ„úsP>ƒæ RÔ«RZ¥"£PãÙ´PSMØäÿB5Uxïßù“‡ÄwÁS»ÁPj
-}ŽšŽ0mt4mñ^3šÿ(¸|¿9åïÙã^úQ5åЬ)¾äš£·äášÑ{›%ívS.Ò‘á6
-}âw|Þ)ÅØnå¨m'Ùå8»ugãÏ%oJÆBþ«_:¬ÂøU‰õ`¦Ö]:«gFïs`%°Ó7Šš²/ÂÉ~
-|¶â¤94Ò
-jm¤A-ó˜dðÏhÄ@1õ¹…™´ÔŽRá¤Æ3`-ü©ÝR3Sù¾×Õ¦'ÔîõÎ/Â*ªš¨ä…—SÚ¹8kŽ>¸)½k/ªªƒòª›Bf¯ë™ÃêÐ5;›?½U~ásróú챑l,Ñc±â6¡6&E…_ê¾ ¤pL­è{ANh­IŸµ}”ÒÞ‚£¦ÕÈ.Åòj4)n_lœ˜ªû=ñÊË.¨/rÇjÍÑ¥îÚê˜Ñû-œºO©¦aµñS¡rÑn µÂ¸%m¦<ÌÏi±<޶•VZfðÙ#ÕÓ,W‡ª™CJ:ýíÝúßÂÊÛ·†Ç:sÆ«'¬ŽÜ§°‰ÓÀ§¿¸žâ[ö u¯²²g´´°|Œ[øÅäÕèÀ˜‰RM˜!x¬ˆ†‰I%žñ#í‡Z;uò]¬¡gÞ‡mšœÌ·?£6<*Çêr<‘£‘l„ºÎmͳ‘õBé±¾õsKûøÊ(ëUˆB 2º~¢£Î÷©KÑQ¯ª&öQy5î^НŸONM:—ÅoM†×š7Qj¬ÈLmù¯íƒ“•=£Ë’Û9
-‚5ÐOÛŒ·‡ÍZ­×±Šõ¹"K9ºØÎÅa\Oú‡~}FŸ>¯¿òœ~qIFòpuæ
-GÅñ&n«~F!LXʬ҆pØnXÚvÇþ坿)söœ†ª¶lUùP‰õ0ÖP8ˆårÁQè£>
-ŠOE†‚BJJKGY¿ê£‹-û(8zítT͉ßý†Dõ5Gïž•=£Ë’ÅŽB©€"±ØQÙ›ctn¨p´^Ÿ ‚ÊQQTÒ[…Å3裋õ|Àû 8ÝJõ¾i=uHoØ¢üSõøÍj.÷ˆôQÃIn…Q_þ«t³šfÔŠŒ<ßZÏúïº2ÖƒÇ ×(¶.ÚW_CGAÖÍÕä6µec>¾NÅ¡i¨ña( :ôÑг¸¦JDI
-N·ûúÏ'ôþ:7êû?P_}ÎRŽ”jê<ŽQ~)h™å¿J÷0+|FE‰Æ0¼=†çÁ?t´¤ÕÇ"ŒL·g±Ó3öâ¿ÌȨyr«Ù²ImÜ †5>ª’@Æ\' M˜å
-Þ-Kg€d|fØGKGy¿j¢ )¼
-ŸÑåÈ•ÄèlŽy­ÿ°_¯=r[eÀÏñ±í±gö’nÓ’4MÓ6Í.‰"^T•PA¡P$”Jˆ/„„„„„**x ‚/7@Õ´¡¹—U iÒ¨h¤ˆFT½d“lº»ÙÙñŒ/žÇÇã¹ì¦I)Ê&aVYÇã™ÍÆçœßü=QgGá¢ç,ûºå鎶;•£Ô:JDi_Éž ½2JŽ
- 2
-*Sk
-¨ÿx+Ý»7L"ÿÚÓØ˜ÄN†R#ÒÇ
-ÑÒQú“úŸ)oßÜækT— È¢ú‘’·Q
-;’j¥TÖ‹¥jöÅKDì(\eGãK=GÏü9 „þÝo¤¥GŽ^?·ù]¬éhng¨ÙQh/:bq<ü°N JGkNäÚ†ÒÔ–¥Vé(®*¦ÝK) >K¤é÷«DzáBü‡Ò7Ïæ>–çYüÔì$¹WËA8j9ºþ§tˆ¥©-µD&•q,l µB[bÔÄ¿Ìâ‹Ä‹sbrRìœÁ·âänhÀxPPÚH\Ɉºô¤’s%DkÈL2¢‘òZÊ+°t¢ÒQÝ)­ú裦ŠHgK^¶XöÑ•‚Ëÿ
-ÿ>6”þí¯¥°GŽ^?·÷]—\ËQº”ZEì(õÑFm¾Ñu4БVk;*úEÉGËæWP±ÊŠ«M=%³½Té­T©øÊ||à>š?<Ïþ
-
-Ým^ü`GGf$¹’|u½ïÞ æ&­Ñâû‘gÆTÁïÝA´‡?HßVBg`ó(©>"iz!ãºI“§< )‡=‡O]úƽ‚‡^ÁÃðÃ˸éÜ9Û6ãÆN…8¦9  }T@]Ƚ¢‰šèŒ_qƒ%Ê)
-(ŸÒ‘N‹A ­n*w…Ë(uVII‹*iÛ†¦Î—u²¦óAç’¿2\9¾~4Ü<¡õ¼´t¾q´|ܼ֡õ_·NFŽ~¢TŽ‚ Âåc+j¦¢ÙgGëõ¥šÇŽú6#z-Gé§ŸR”¼ýr콈ػª”HpTœÆ3otŽŽ—–Ó¯<•?õtæ7²6ÐVCð¨À‚¤§?ª>…£ØÝä4ÈJ&ÖÿîÝ`nÞÍúJ¢*_{ï7sß-þ˜Imy»£q]›ÀÕ“¦@+t,¤^úúkxä þí4_zä!œÞŽ[6á˜jœJP7çšU ¢%¥cI|zIé¨j1¢k:Jqšì¨Ý^ÃÑär_ö[ƒù·ÃÓG­Sú—¿Â9z+­Ñ;2k:š ;Ö%O³£Ž<‹ã[W°£ŽÅ¨Ñî2šÊAJiŒ«5§´73v4•yl«øüÛñ /¦gÏÁ“_ξõ½lòÈ,þ{bÚ·ŠJjŽ»L6rtíéü˜Žæ]D£ÝÂjÊkñTaf8Ä'IPÛË‹ø§—pö¾ûo®¡»wâ¶ûqÃ8NŽáx!(5Ѳ†¿^Rõ´“ÒÎJSSR«yÕáØE=-@pT¯¬á(\í9]bGO ·oÒÏ?GUzäèõ3rôeµ£Q»çÍúØb½Á}Ô8ZsÊ>jÕL)8¢¬¤¥CÅtè‡.ñ®~³mQñL…âÌ]†£Çàø‰ì¾³ï~?›Ù¥˜[vŽ’Ír {àÙ´Üë}÷n07s–mý#(è£]D9Å–Iïë¾øèá"OyÚ<‡ÇožÁûñôI¬¹øàV®¡›ïűSØyMä䣗wK'”^“æÔ8jN«÷˜±lç*fG©›š>ªÛ쨳¼†£õ/É|ÙGÉÑ]Ûôs?— GŽ^?#Gÿû YwSõ÷ÑÊQ꣮S:¨–ßí£®,¥–h5šÊA5‡Ê¨‰U< f´…\Þ½mÈ‚ñüʇpl6;üjêÖÒo?“~þ  œœß'yoKÅYEéúßÀÌMu´*ìÆNdŠ“vû¨éûù¢ÔGÕ
-¨iœCe´TWi@e´r”ú¨Ó^ÃQ ôÑlI§Kaçb^ñWæØÑ¿¾>:£öÓ‘£·Ü½£bàüGÃ:;ZõÑšÕ
-¬VÍêøXTR‹­*éjJ%ö^¯®R²]-,‹
-HZØNž#,·²·Î¥ûöÅT}¾¾'ýÜgÓ»¦ò\äC”ŽúèpJËÓêî””G+D+GËOÙ}Ô j¾ø*JÅ“GõÆ)Ü¿ÏÅÀãº{ ˜ajê¸ÔÐÈ¢¦€V¡êiZi?¢•©æj¿£ª#ܸì£NÄŽº+L©ÛbV£ª3ÜGÉÑåØÑÂÇ?£òã‘£·À½ƒS9J­”Æ•£Q› ‹A¸P¯/>;êÛ¥£¾ìÔDá¨È´(%é “¥´ý®å¨£DÜ––K/A*D®5íÔ´ÕIß?ýýÞäÂ;ÉW¿”îÙ›îcD¦²èKX êÇûÿ¢^·[ý¿Y£47k¾.tÖGiÏÑÕ)¿ƒdÕ;ËH (¸ê‚g ,×WæàÕCph?4`óF®¡ŸÞc5Ø8É54ÐŒ( ê ‚% ™•Žäb¥¦Á²:š·õѵå2ÚT^q:ÔGÉQê£äh2ï_}¿tô‹éýPæÖÈÑ›µFÿs-G;q3Áf-\ôk¥£žÓòT¨5%Îly-GÍöµJ‘JE»T!u$jÒ§ÝšS!U¨•:*{79v 9y<™gžÁ™é)å ¯ØQBtäh/•£¥}pv½ä»Öã ¢æ´r´°³ç¨ìè©ã0{þy&ë°ýxd<t?ø6 JM”4¥J¡Wè¨r §‹ŠÉªƒ’‹>ÔÐ~J£C}ÔIuZŒ(URÓG­–-vTv¥>ºô;zòàدÛ¹:à3c{üx{—熔¶@Ó„DmIÅÞ€¨B¡(H ªZŠ* D ñ‚·ü5ˆ*QÓ¤ $"Uš ( ¡Ðš4w!Éårk¯×ž~?Ϭ׻·w9Â*oØÓO£Ù9{wÇÞùø;ÉîÏðŸüxâè}üþ?Ws}6í¬-èb<5ÏÃùdêv’,øÁ¢ãv"7(PÚ‰ij¨"”E¤Š€¢¦LvÀT“;‘ت̸9¦ê”ŒV •6ÂFbeŽã!×·æä™“òׇaãXîÛ'w=%=_j<ÕåUBuúöC&á±@X$Ë–Zúß1ùºsðÅVÿí-ô‘oÍ—™UoÚ­4Wv8w¸a’1K&l(bjÕÝLû®æ^ýP;ªO¬ŸØ"žÚ!y@lšë“¢ë¦1ƒŸ&†b¥Ø²r¹è)àÆÕƒõ8ð -À(›\U ÔP€£H©›b$ Œ¦)uÚ„¦”v y4õʶ_.ÄYÈ£ñâådöïÓg'_yÚ{õGRzGï^Gÿ×r4íôpt‘»©çXG!ÆU$r´Yh¤Ö=5—u´·ÄÅÌ4¥¢ª6é–
-H›òìiyêxyçŽüÂ3ò¹½2ŒU;SA„šv!´pü¶uÊ4³@V~<(n'xÿ¯ð˜]Ò¯ï¶0C·Ž›æÂ;j.9 *%:
-×H¼â€(tê- Ztô¯ÄºiF<¹M<¾U|d-*f±&,ÖÄEÄNc§)s³1àèPôlšÄé–Ï!GÝÂ:ZGRpòhÓÑ^Jýî<"
-µp)¹öîôÙ#ÉÞg¼~â蘣“]CŽfy»$àè÷’øv-ú^ê²<rÒe!CD£€(”Oú‚ÖvÂj¬_ÖŽš”.ÅØ:ä¨GÐQ“ŽH‰{Än[þëåáÃò½÷åg?'_üšÜ´YIÅÕ•’…@¡hПHs›Û¬z‚÷ÿ
-ÇÑ¥‚LØ5RbK™¤ #-%ô™#͈½¸Ue•P¸u Q4•’.èßÓoŸ’Ù‚üøGåÎGÕö‡ÔÆJÐ-1剨‰+nom_Ps§åhA‡5ˆ6õ¥íÀ‘èh—ð õ: GÛØGYV;Êå/æãò:zûb2û·Ö¹#É‹{¼W¾ ?Ɖ£ãüNjÙ2 Ò“åY!ÑQ?°ŽVy4Ý,t4Яʓ«˜ä´ŸA+/G”ÇF;êjtT \Ï!×¢ƒï#óòÖMýæúí·ô;õ¾—ô¶­ö«¨ n¹MUDQG1Ûš’ÊÖKhŠºËä×ñ•ju‡V’F V/§œ¡pÙŸO¿Ïä誤ÄM€²jª/4DO¸â ièJ—‘N[Ÿ9­Öß—3±||»Üù˜|pƒZª„©õ$QÑâxס7:\aÇØA®úp.ç¨AŒÄ¶Àù9î. ÃºØ‡Ö$Ѧ£HiË8
-yÔɢ¾ãª… ¸™”u=ß:{(~ùyï;/O]UMCÕŽBµ³¬i-˜Gï„< œÌwÑQŸöõ‰EYH¼·½3É­ÈÄrHQ^å(®j‹(îH™@÷”&áÀÚG=&ÛóòØ›òô =èç÷êÝO8]”VÏÇ€
-çSWàsÄÿBDSK#¯Zc*ä]ÞËžï 8TCskI~NÈ &Œ!
--Àé1,àûD"zñŸúÐëúØQ>wl•{Pn^/§¸Ú«i˯àœö+ª[®¬MGÝQa´™Pq¤´ˆBy]ÊKL–ÐzvÜ.¥ f>Q?·}¶ˆyM]r›“[\܈ËÙ(]¼Œyôôø•¯»ßþ†š8ºšš8:†GM…6íäyn]LBëhàÃ<PD4 ÇàÑÏ£fEùÍ<ª
-.€µ »r7”
- ‘9:
-ËÓä Urß­Ìä;ç䑃2Oõžgõ—¿¨“X ¥
-ŽBe íçÜ¡?…d>w Ø=¦ÌW¤”–â. ›“‰7œ)ûB¿úöõì“H 2x
-hi¥ˆ˜EÔÜ{³/1©ÔtÔd®E&›‚ºU]ê(ÍPÍ¥ö`Ì cmÂÚLÝ6"ÊþíËëGÒ8ûpêúù™“¿L~ú=ï…ç&Ž®ª&ŽŽ­L$ítÑÑȯÍB–G:êÓGM1á¤é(®X}—<Š »FTK“Gu/!’B5oBÊ25í
-·z)s9wYž9)O—»>Eöî%;v!à(ëhÓË¥52Rz/‚ŽÁQ„“cDM]êhýr¹<êë¬ñ²vÔcö"öÆ¥#­£p\ån[ž{K:€¦ÖÉêma ;M]j¯TS*‚ºŠšr!œïzHñ–ƒP†ÒªªôYö[C©ÓS³F´˜´ŽšAã(ÍÐQ^XJ« jq«Hjòhí( ôõXÌÅÝ«qz =õZò³x_Ý3qtU5qtœ”v:i·Hãh1öÛi'n9Y³ˆ¥MCš‡+ ½ý\/€BËûk ªŸG›‘4$(±GKFû.`<•6ƒš•ß'£2ZÞËW7®É?ýN<@gbúÍ—è§ŸDGq–Êœº eàÌY¤”nvMѦµd8ø¹˜3:¦F¼éè9‚åò,c@ø
-"ø?(øÂ‚¢ˆ/„‚âßà%i»i³•Ö`’m­m(¦iŒYóT“Ý;sÏ=çÜãï7çιggg²‹,è‹/—ß=3÷îÎݽŸûïúÏ< hêèú™:º™› (ò‚åI<(£^꣣©ƒŽF:l¢XBÈúŽDµ£!AGá{§&À¸`ŒÐ"èWÀ€Ö/A…9ödoI^ø“zé¸ê.©¯=«žú¢ŠD1p‘J–¸ ÇVlð[Q8UÅk˜G¥ªöˆæ‘Zh¿4v}Rå”—€åh4pû­tØÍ'ÄÀ9ßÁόŴ~Z…}1 <ôÏ PMàPXa½\.œÄFí=¹cF9Œ5tK„5t6Q h›ŠY…p¥Ç xÝ/NBF6Üc†±A†9 ʺYÚ5T;
-+€(ÉëÞ©ÕÔ‚Gõ`¥].ônÄo¦â6:ºòtôDzÏê ¸pSG×ÏÔÑÍ 8ÊXÞëçq´ÒŠ»©ÛmùyD{‰×ôÑGC:T°²¿ÛÁMX$¤.¯k3 t•£6¢fEJ]ICk%ÌÜ L–}uù]õâ1Ü>þuô9µm‹‚Ò ¦ÀÔL¥YE][äj­‰mÞx/'­oÌQ ŽŽ[¥V)6‚Vʗ㽴߬c?ð“H¸ŽR|Âi%¡…PìWªäï_f'_æçÎâ›÷BîÙ­>¶…Ú Tǯf\T3å<“"æÂ/«Xˆt0G%ÊŠµ£¶“µ×q¶µkèÚ>ª5pêÁìBCG1G{µ£+ײîµöâ›ís/e?ý¾ÿø£SG7”©£›ÛQè£ÚQè£#ŽBŒ£‘3
-·&ÆQc4(8œÁ·„ÓQ%*¨‹–î¬0À"H ½sñšZ8­þpF=òiõ­oª~UB€Í{%¥ñ†I^Nê©“â8ŠrÖ°§»°ÝˆÑN±~\9ê¨ p@W?€àJQყÄþxäƒüì«üÌ)ö¯E¾c–?|XÛ;j&A鶘f¤Ê”˜!¼%xZòŒcÂ…2
-ˆBⲊ:ª)5Ñ+QYûÊñŽB Ũ£ZPã¨Ó¯uÇ!jdÕˆ‚¦Nî‘{èhy#å·²Þ":zýö…ÙÏàþ<€¦Ž®Ÿ©£›p´(ò~Q;š8µ£©?ÆQDt ©Í'$’e,Ët`ç} ª‰X®>Ü·Õì£ ¢n¥ÚQ=€¦P´zKòµùê¹%“G¿*{TyªqQGÆ–Ña¸GëøN3ƒAf¶_uÔèúýユ’5[ÿÍïa!ZÃ3ÁQO¬ªíæ úr
-(Vu=ÃbÅxò0$ÐÑß~Cþö7ü­7˜ë°Oââ»vò,–[Rõ¡¶jû4à´ãbõlWÈgÜ+Û¢vÕeê¤@Jý~­¦q´aµÄOa(µÛêH…º¶˜jGC㨨ÏOÒuÀQ|©‡Ž’££åͬ¸‘õ®·¯^l¿þrö‹úŸûÌÔÑ eêèfÆ8šÄ+iØi7óòÄ­MQG5¥€ 6¢DÖˆŽÍ€ÒU|ê>Zï’Æ ý…t
-¨n¥0Cï>a€ª
-¯VLòž¼|Iž8.¯¼+¿ô˜|öËr×N…”*‘@IãXs7¢¦yOÆ«7éÀÉ'äTc»êðȆFíͨ—:Þ„u­iä [©£W)¡à_ú?ñ"?wV¦<ôß;Çvï.¶mg6„·9*R4Q4’Ž×ÇŸ•MOM -x
-²²*êÕˆ¦L;JÃô©žaÀ6Ѝé¦^Y…b•£0@+DmG!ºBõ4ŽjJuÕ}¶°ŽB¥w#~³vtù*:úÎkÙ/â>0utC™:º™GË{ý<
-ÑÑÔ­M¼ÚÑÄi55Ô´Ò¦ŒVè(¼S;jS:ÉјŒqhІé&ª¿Åê&P¸Ü%\À=qGápû?þ;ùΛòà^ùõçä9<•ê‹Ì^ÕœMŸÐ'‘z¶·æÍf«‡‘½nBURÑ+²*!-=‚šú¸»± ¸¦õõ5O+(~Âpð G“PÑJÝû@žg¯,ð›‹PCå§ò=ç³3lv¶Ø:Ë’˜µ[<ôd@à/ŽÍ/# “ðÀQ°S
-ÛJ*“iÑŽ¢¤Pq“ôë¤Åp·¨ °¥õY 'jƒ
-[X1}T;ª+©&S;
-eT¯À€Û.öQç^$n¡£½Åléýö• í¿ŸË~ý3ßü³L]?SG73pWñ"/VòÄívünÛ馪Ûró˜äm¿Ÿ’~FûIÅ"Ž·´¾“SÕÜÕæÞ¶ïöa=mÑ1(è!«XZÕ﫦>—T—4³OQw€‘h…Û»wøëçø™S|¦Å¿óm~ä³
-š+œ
-”ƒ-¥`Ѧ„Ö3 #ÓìŽTU›[[èúmR€£ø¤HK‰×"•8'ëZ]1õ¶yÖpl†Ö'DŒe’¬l;Xç]^¶á:òüyþÂ<¿x‘ÍtØþ}lïöÀ.¶}oÅj[ª¶FUBª”V±ªû¢ÝÍ®™}¸J镨Ä&ªÍ
-™ô1ZYHÆšY¿d‚¯‚Áy•öUÈœ ¬Ô]¶ÒES=Ö@u{žŸC‚  dz^×#+ž‚&ÚódŠåX-ÇÅ¿ÓZ¾ÖY¾Úºt>»òVð«çݹ9*ÉàŸí$€ÿrþÂÿóûíÿ'SG73¶£m¯v´íå Í3·q4vïl°\ë¨YÔXêwÚµªy›Xåh0 t-›1øÚ
-‚b£s00@%…Éóeþö_ùü ¼ßåß8*Ÿ~Bf1Ò  Â±„ËБ¡[U »òÚõÔÞ5dެG!º(¯…6P‚ò|ÔÑx¸› ?8l÷#|6a¬­X\b@Ó„3¿‡+mŠ4" ÄÝÛüä<_Xà‹7ùÜtPv`?›Ý
- ò³2 Ôد¿7®*€ãóËóÛöf“Í&mhÚ&$QZHTQñÀy BB€T@­<ñÂ?Ãø+ 5Qiš–þŠHSDÚÒ‚šB6Éþˆ=ž÷ž{9gîøÎx<ú°Rò`éÈ:¾v¼±×þø»‘%û6 ê á.Ôˆ•—SAÕ¹ÖÔÁoA©Úr4JgÕˆ“¶¦ê¦p"b,Ú‰ôKDµ£½¼v´ÌMrTQª:s¹å¨=ªFØ
-ÒÛäèèzåè¿>tý ûð!$½­E­­ÃôAÞžY8º“ƒo8ž'“­ªGcƒfØK" ' %QÉ)Ê<VïMG›Äú|ÆÑyD+!ÔŽV¦Ì¹¥•reá4¾UxfÑ“…#hp—ŒÚôëdÊgŸÀWŸŸþöî1 «’'ìÕÑÙéèv|j/õI§¯mG=^;ÂŒ£ê¥étT·)NÔ£C#ïãSMò¾È‡faò%»ˆ1'üïïø»| ÉdOc'žf»—pÇ͇æ÷ °el˦”*:• úµ«såhu ª†URj5µó;RêÉQÝ£JÐV*GQPE):Zîä(6¨vÔºGŽ"¢fêÈ”z¬‘£ã•£7>¦}ü`í(%©»p´{Žîä(GÓ{I`QöMêÑ%·v”FL!3ÅÙZš»r´£óšê;Tý*·©²)7® D‘O„S;jCõèw‘7>c/Ÿ|
-ìBß“ûwQw{ =Ö³ÈQ3“¾˜á³™žó²ÒUQ9Š{ÓÑ8«íìÑ–£q¶­£8vJŽâbMjGqÑŽö’ªGt«êQí(ß²;ý|­?¹9Üú´ÿ·7âÍäèG+ ¤ÇAMé¨Äߌõà?oÏ,ÝÉ¡^áÉx£v{tàÔŽÆ&õh45R»8O©vQíê*•ZæÖØ|ØæƒÏ%oí(ª©è?Y9²Ê“"ta¼y þ|¼<}
-¾ýMÄö¨âS%¦gU@ªE7Tç¦öRÜGÜêþ‚›rœ¯ÔŸ^ §OÉÕÝÙp¿DÔ÷ˆºªnB;‘RÏ6>ûˆ¿yž_8[L6‹ã‡ù—ðý»øÁUþÈ2¸È*é´‡7s|H<é.QÝ í$Åïh÷hÊ~>ÃdÓÎySuF©ôòÊÑ&¥ÊQ¼TŽš“*F[=ê%ԣƦcŽ©GeâÈÔƒQÀÖƒb½ŸÝ¢EGÿúzœ¬‘£û÷›L”oë…£÷…£;9ø†3 ­'ž:XähßFD“Ø® ¡ÃÑæÞÄÿúÄѬ6}$¶Y±ÚQu>?‘HA}¬.õô-ºtYЏ†vaK@2q>º
-/½›·á[§á{ßå%#½ƒH*P}»rT-èh‹ÏÏgk\9íQí¨êQ•§ºGýFwëÕ1Ž'þ…Zó¡o \zÎüžžÕÞ]ìä—Øñ£°o_éóåP,¹bàˆØ4bIpzPÁìI²P9ª)í,Ñf¤ÚŒzTíSˆÎôh“ÌíÚ4ÎÁ‹~Z;ªUƒ|¶5Óe¥­UŽZIí(ö(:Ê6úé©G7¯õß{-.6Ü_ýÜ^]ívTØ8þóöðÌÂÑrTLîÝM\IŽíÊÑÀ Gã2IÑÑ€·¥lú§ýÓçÊQ}‡fwÖ.Îz©Ñéœòx–Oú¿á“
-[#(X AÚ¦`‹ˆ&`4"´¼ØÒÚîn»{÷ÎûsÎñyæÌ;sï,­É&ðÃMžLÎÌÜ;{Ûû™ïBÏü¶c‡¾­ñ×^åOáïã;æIÐýûø¾]”¤sï{<px`‰@' YAIŠÝieF*;;3´yå¢fÃYµ’5Ì˃ Gq0L;ílÊÚtcuÝÉT’£6¥µ‘£vY¢ê¸UŽšޱFŽâ®¶”’£ü9ÊWƒ|9Œ.’£{> ûå3GovfŽnñhZ²º’¸fÔs*G=#ö­ªGÉ­.G•šµ£Í#…ÚÌÓŽHƒ–£¸îK‚FíÖ=ªL~=¬”m$/“àJpвze.Ë8œ·ó7þšŸú}þÖßákÀw¿ß#Ð/U€d`Ò×Ђ®Pî:Z]¢êÈÈK-fF5®>^ûz¦ÃzãW‚´ž±,›Óië¦Ù¼Qª3ê_Û6ä¥ òÙcòÄó’ÇpûmpÏð‰Ý°kæ=±{NØ ‘I…¨âÐÍÁÇ›.ºBsD›§¢jP>'¡ucÚ Õ©Xô&ŽN›:–5Áœ¶uÔºêÔX·"»¬UdÕÉ,c@vºIY¢Ç£xPÇ<’£b%à+Av5Œß'Gÿòl¸`±_<NŽr•îØQé£Bÿð¿l™9ºÕ¨‘®,'Ž…vš£¾IŽ2­ŒQ¤T´õ-DkU€ú¢åhŸõnÑêQ¿Þ•ã–U äøjÍ‹TT—ˆ±èêÝñ§)õJ3¡­åëïç§Ÿƒ—OÁáðÃïÃÁ[ÁÓi°Y™FL"¢ŠUå(îªãv£Ô£¬l_O”ŸÕôh™^¬u;ŠÏ¼WÜâq|^°‚nÔâܳ¸ïÊh _9+ûùæ¿äÎEyÏ!ºË[æ`Ž¡£bÑ=S0!|üód‹C<nfˆN;j7¸µs%cD•£¬·aé¨ô£ÊQ/nK™NöhÍj;I¥;RÓi8ª|EGÍ!9Jʦ–YNLjŽz”µKDi"rV'}ùX¸+`?ÌÜÖŸ9zs_û™£[üš:ji#GÍØS£—1ª}PN;ê5º°ÓÑñ‘¶£
-—¦Ó¾¨ D»%æ“Z7OáÏâZijyOϘÎâVDäè Ç`÷üàøü]Z¤‘“u†65mã%¢2ÅljZŒwµ\Ï×ǹÝDcø°@ÕñîœÜÿCS~é=þÇãüÅ2yè ¼ó¹w‰2t©GÃ4âs;Ó̈bÑI5¯(«1¯àÄ­•maYtƒê–½è-ó‘Èôã
-ÔÒQéÅ4A*ƒ®ídµ>‚¯,ß‚­«ÔrTõ¨S"Z;ªz´uôëä¨9ú`ìhz¥rôÌ3ám ì‰GÍ0D2gŽÞÄ×~æè fº²BŽúvZ•£Ž™2½êÑÚQÅžß…Öt)6Yð¯ªLÞâ¹îQ¿‘¶;w}Azåˆ*uAŒ=ä5ÅAJÕÔ)@_}‰(ÅÜ|ø!øúƒD•LFR6ÂT­ˆâÛUŽz²ƒs5ähë7/ï̺'¯ž ß ·)6àìI8ù÷-¾k‘ß{˜ïßG‹¥~¾´ z6,ø¢o =&>C¡±œÆNJP3aIaærºD7KR5^AÑÙp” ÐѨ‚0L)CýX²H†x6ÞÎiDq0^ÑÑ2mIb–ê,«­mõhJ‚Ö|Ö ìQgHŽêëøÇ\gp5+,W=:x»ÿ§§Ãƒ»ØÏ~lzÞÌÑ›ûÚÏÝÚÑ rÔÖÿG;ûoÚQµ;á_}*Ž’‚²zn›=Šý¦.Ò|ëšÛZ+5xµžV]“«ª
-ŠIŠSÃL”Jò²ïÀ¹aÏ™_ú Qºñ'b2ÎÆï#pKrKHWHÅàKº>ú’ò²û類+‡‰_Û7ge#«íY„ù+§áøSpùØ»÷‚·ò[¶“ ý@†ž í<t¨YKÉ…S¢˜¡ªGݼªÌ:Cq×ê ÂÊiÔ jJq=ÞME˜“£ŠR\#„¬ŒÑ&‡õP\&]õ™ˆ°48I¬½LºC[EAíÔ°3'mõ(ƨ54YRõ(ŽZ¨5¯Û5ežFL\÷åj
-KKY;*T‡k•*6'>qÐÑ £A 1"“”ÖÓ¤Ô ÎšÒ±©‰ôËÅqŠQå(> \¦å £æP·1L£ŠO{´07{ñÖÈQ Ö¦££ü*9:ü9úâ‘þ}Ƕƒ5:vT””¢£Âœõhûk?st‹?P3ÅÕdËQìÑÀ;ªJô†Ž6ËlúìôÁ¦šJ£öèô{Õi[_¤i3æ#á%éné¬ï¾Ïü’ëððCðÀ ¾/Ÿ‚³' ¬G¾ _ý2Ì{ä(`ž™ˆh¡‹Â·©-õLx
-BùzÇÞr·»³óíó<ŸÏ<sss³wë/Ñ6ùdò̳ssÇdçÅ[{ñE¡™ãåå•£=¯ýÀÑe~ }%JE&hFi_A—£¹µž˜[ËÁµÔ®O濨×Q¬Oy¹ƒ‚Š6­‡ô¹;_¿¯¾Dvb}>ù8è yÇ|*Ô£¯ÂÄ5عöî„O¬#D‘R'ÞP‹K’ë¯ ^G¿:§´訤”íN“P‰b áRœëWØfÇ2]Ã5Ábñé‡ÄÎ'Øø}¬nAÝ„ºèш©3áPE"JŽæ^’‹ñŽæm*M]ÐÑ"¢8.P‰JGqp!u,¶¦Ô4ß/á*÷ž£ÅEG1Fm?sÔŒÈÑô¿Õ
-çzÅEG­€¤ÄÁ:ª!¢3Ô£f›pEGÕŽ©tlÖÌ ïxõéKcoª>¹Uýù/˜j!G—ðÚ]檇Íf xæ¨-|Ï G]mÑ],FëÑ"¥‹õhîèRz´xM®fÑQÙ¦¸¨©´Ðƒø>;6ÂøÚñ‘ßBÒ†o~ ¶n‚ZJ:ªÅt¼sÞ<gNÁêQØý%ö…mlõ
-¦Æ„( ÀQ12ÉQDJí*5vLmêÊBM×8F”:*"æ£X¢JšìÝSâ¿W.‰ÖŠÏmUG\¾(îM²Ç?ÏžÞÃVÔ©V‡+± Q ŸxÚœ¸2KcX¥è¨-Ú£x,:j2µÏeãÆÜò‰Ïj¦hjQÇÞ-›ÝY FiBÔM5µS5@«DóÅcî¨ÕsTö(:j¤Sigû¹£Ð¨&w«ñ¤ç߬7ÿ9vâ`m÷õ§?#G™@5Žþ»×~àè2?P#•ŽV¬G=st±íïèÒ,®—îèbUŠd掺øMé~8¶B^^x^?Qöï„Ö!ü†50C¨à
-žÌМzƒ¿s‚û ±~µØóEñÙ 0>B¢¡µ¯Ø‡®ÐN>xs3S*‚©Ý•hÕ"D'n°÷ÞaoçÏ
-Ïo<Dºf Zìo'ÙÄuñåbÏ|ØäšO,ã_6¢#Èóíïh¾–‹¢£(V47Ș<z³ŽbŒ¢£y–b4O{ƒµØ£Y†ÎžÖ"au¨Gk±p¢ÔËÔÑ
-)N lS=д®f¤Š|bwâÈ…ÞFA%¥„¨Ò6UÇNš^Ò@D‘R¯{«~÷ÂØë¿©}ý)õG?fŠ©ó´GçËŽö¼öG—ù¦Žr–õh¯£Ø£RPyt§®w_òVº`ÁË–bgŸ_ZêQ<UCÊMÄÙÃÅû…ã€pöï‚íŸ!§¬ª”Qšv$¡Ã;\ø|ò*?y\œOh‘ظNÙ¼^Ùö_·‚× ptü
-&-Q9«(Lc4¸°u:¢žö_gšAÀ¦î°3ï²Ó§ØÕË"èP†"¢®ccu6Reã£P7¡Ó€c¯ñæ ~à«ü‰­Z¼ªqWáj°
-Sʸ§¬å?È6mLFêQ½¹Uf;ÌÀ×U¡QT„¬ã³°ËÔƒ¿b]f—/°Û1ËkÆÅ†OŠÖ°U£l´Fˆzx:¬¬Ã° ·®ðÃ/ñöß·K<¶ _~Q*T‹—KÔb 8*í,9*™£qÂÌ¿V‘F©c±DþÙ€å{Ag‰RÇÕ(EÔV Úø/JùÔºäh±GéØ5¬4IóUgÈQ»K=*ÅÕSñxªìè‰Cµçöªßý†š°¬GŽö{íŽ.ó5¢F3ä<0ô°jumtT“Cˆ"¥žˆÜ$ut–:éŸÌ¾"¢KéËâGîüöþ`ñ‚>Œ|V:ê1¥§¥R V8­ÑKÿ D™Ï> Û¶€§€¢h'®ÑQ•( hÎ1C•@°@m7Õ‰•kgùÕs¼ySˆ€9FRu’áZ²öcÉøÊij'<I‚NÒ˜HÚÓI0u×SŒ…¤æúµìã÷³5+ŪºuYÝaëÙè(%#ŽÃ•ª þ=ôK¢ôÛÏðG7Rb£…x>ë%v*–²Íç˜,9šq "Œ?Åê’” º(CSNþ©ÓÍNóbzÊÍâdŸ†îl}Ê#¯T;X¥ÜŠNú“ŒˆÕZ‘V ³ô4ü T3Ö´YJ5âÓt<ÚZÓÓ¶ÚÆµE+ëÑøn-nTÛ·†îœ{óåê·ˆ¾ÌP™‚Ž"œ½ó¿Ùþfàèr?P#šº2VvÔíQtTÆ¨ËæÁYjÊ>ÎõêRê³xÏ>Žšq\SgOP#ÐjÇl•bôÌ)xíh1Ø ÛWÃî'!;ñèÑT\ £¸‰ ›^z,pXG‘5xg’7oð©›ìÞ$kÜNüV¢òDa„(©Ó©]!_‡=PòX=
-kWÂýÈ96ÓA>MG#¥|6Sj
-ý¾+gù±W8kó}_áÛ·P㦧ÒÅ5f²4wTÂYîQH‹¶àhîbŽbQÄÞÊìÓ£%Vå fáL•Žb†:²£•˜ø4ÂÌQ# /©Aý¬M¥£z›ÚT:šö(9ªÌØJ«ìht7sôíWªÏ?+ž€ºsàè^û£Ëü@¨9bP™•Ð3ÉQWs”(噣²GKžõwô?ÚÌ«4¿f)Üba<¤Ç•(6Ù©UŸáô_àO‡Áð=°u-* ,€*'>±DÑN‚3Îò71LÍ„ØB’Œ$¥´¥˜iB‹'3øÌŸfA+IÂD
-ŽX|¨‚vÒŽ«qGM‹¯9÷wþ»_Óbÿn¾ùSô)²*³Õˆ)RÑT©f±G³ -ôhî¨dŽ– \ ÅRžæRJ‰ó J¸Ú]R³ˆè‚=j$ä(öhÉQ¬ÏJ—b4w4ïQ£EŽbê÷2GU?s¦ªÑd-üûõúÇUÆq|fç¾3ë8NS©¼Uâ"D«–4(âR•´!¡RH€JTH "B€xÁÿÂJÑ$M¨šÐRÒ¤)MC‹D¡´¨Å¹Õ½ÞËÜΜá÷Ì9>{vfìø…%x±Ò£Ñ™Ù3ãõJûñ×7¤£/þ>úޣ壱¼c–™£[øÚÏÝæ´r4ËbÏMºŽìÑŠÒ82〓£Q!mE´™­jÖšR‡³uÏVÅD%©Øìqf3æ”Eä_`§ŽQž~û0•(¨R8êÒQ•¡X€R\„¬8â”;«â³[0kĬDzg¥òQ¨^‹eVIÑ)
-ߢÁt°ù×—6=bΦ¦°0ª2T—:bmBAì|ý%~òqZçÿø‡¨Añ*øtª7dŒéQ¸K<DÙ)Öò"+«™8ZC±Ù—µíeunuGkE{ËrÔNé-O8ꢦ•Lõ(uÒ‰£U)9ê¦Eò~ÀVÈÑäºìÑ«ÛuáxôƒÇÊÃßšõè–¿ö3G·ùµÓÕµ$ŽãÀO|k˜„¨p´×!Gƒ"íU”v×ñÓÙ«'ÖúõÚæÚþ®8E_n…Ou——g=S>ÜLؼό¬¸ürqâ ¶Ãc_ú!
-\1HUXæd'àÄÀQ€*¸èÄÒQ¦ ½„…=¦‹mN¨ Mñ@³È\Ú uh0séMùDÜ2ÞMx„ ¬š×«Øæ‘£E‰ÇAGTô¾òúwüóü›‹’Òr4ÙÐlК©ˆhᨛAB?Zg¯Ié&¬ê®­Ohu´Ù£ÊQ½Gá¥p1ª;Zë \wèvV}{µ¥Gá(ztxuÇÒk».žŒŽ~·<t„ÉÊ™£[øÚÏÝæ´rt<Ž»AâuÈQÕ£ÂQŸ‘£˜ Bn5áT"êŽê‘ª—k³GõSq‹z©Y±Íç Gç:™d‘E’¾8}¼˜ØâClÏ=Ä
-ÎYÔ¢UvŠ…ˆQuG¬ÕB°ŠµÐW¼d§2ER
-ÅP›¸è"X—ߥÝ4L©ý19Ji˜l>„=Z™‡ÛðÑ¿ÂÅógøé'ùwð¯ J‹TLÓNÅ*MÕ£naz™tT1OA(|Õ½Ô°SÕ'ÖþhêU¸Ý¤ ц£vŽcŧæ(z”êsL=êRªv¬1JT$)9ŠÑÕ{4¾&}÷ò®¿œŠ~üýòËàƒ˜9ºµ¯ýÌÑmþ@í´?HF£8ì&®9Õ£s9êåé\){T9ªœùX S]D½57á°æÖýµ{##³b:Ò{ãìâŸØé§Šž_^dw„ÔHˆRLÀĬ[J…ˆ‚Ia$å"NÓ<Ìònš÷X$ù\!OÃj³(T¤*8OîŠl5W–$œÄXJކiŒÈ©éz;¢GEb¢;‚â¼OUzê þ‰;ùWâ¼]’ ·±Üb?FgU­+D'=J?N7oÓ$Õ÷;uS…Á[ïÑp,uÓvGDöhÓQ u‡ÒQkÅ5×&=*EÆ×ÉÑw^ÝuéÑOXXœ9ºå¯ýÌÑmþ@§õ Ù£]3ÞaÇ~!U=ª—bÓQE¬ÊÓMz´Y¥µQ1Z³S?E†"Fá(֗α㳅¨8ø`qß=„¨(Q,£bðI‰ê Š£3Ê£œpBPo,5Åé|™wñ1ïåO™dG¨$6æfÿ*mòFBPì.£}Æ{¤N嫿(U‹“n1éxöÿãI~ß]üÈÃ|wHWð*¸Õ{T¬Wi…h…VbøâgÅSÝYSSW¶ö’p|*Gõ»& 2ÉçF=j§D»M Ö{T9
-DuGÝ19j¯¹VŸEšƒ‰£ùr”/÷Æ×¢ÁêÑWŸ‰~~´|ð
-?ñ[þÆ%þùOñ}{‰Rt*~ÃèSŒ
-)©57Â_kjá¨Ø¿¹£bô
-G!¨Þ£qÇ­<¶‡ÒQ¿¿îèŠç®;Úø|¥Ë—1a~zŽþãÜÂ;Ã_ÿ¬Üó‘-Ú™9z‹™9ºÍc¸ÒQô¨p40G‘9 ÿË~üÈqÕ¯êîÚºº{&c„Cbl‰"À€¢! q$(q
-¥à(<O×N[qú·7ØÙ5vÿ,Q@TF¬Ý€eM¸ÓÆ¥m&ÂE‰zyªz¬Þ¿ ,…ÙiµˆÕ ý
-{ój¢6ÒÏ%Sµ£8 Þ %Da¼ß1|†¶…ß ðí
-¥ATýœDi')iJ›Ô©µmêÆ¡žVŒ —þ(QÓŸ ¥à(
-|6GÊQ4uæ¨åc¼B†¢£€¨ƒÇ9úÓÈO<Ê2[õèÂÑ{üÛ/ÝÝ‘N6aÙíÍ8"¿5ñíq
-å(èÌQ]¢†£V…F:…ãLDåùêF%;µš~ZrÔ\Ûë×jÔusD=z1 Ð<û@£¨¯šRèQzÇðî!«NØé9òÒqü%+äÖ7Ÿ< (7áˆzcœn†6ÃÑ 0µ"(-ÀQQr†%G+К;´€cWÜÆt¹šî¬JÉQìÑ!Ö*8êŒlwŠˆÂxcHRBŽ…£ÍêQíèäzïgW†ÿù#qä‘…£;…£»<àè”g·6ÐQ¿5 ìI`¢¦£Ìè¨îÑJ€VÖ§vÔËÔ à(I©ùÔpšŽ‚š°èY£p¤åc#~áõ|õö­gØÁ}Ìá¬ä£TÉ£¤&jšÕ%iZ“’ZÖÙÜÕÑÚ5Ñ„Må(Œù¼n^¢Šß)”":Ú8§5ˆjGa
-=Ú¡£|#ä›ôv/¾Ñ™\ï]üó
-¿þúgbÿ…£;…£»<ÒIb;{w=vœ¸=y,
-eÒAG‘:/÷† ³,HKA9ï¢y&,
-µ|5ÍÂÙÝLÙÖÊ$üx…—k[ê'ìtS\8%ξ*Ž”Ï>)÷¿O®pÉŽðÇn#Vwj)™å&õjÒi}­ÎR•í$<Œ9å¦îÎZGaMWÁMttýmµ¥¥E™â¢ÿj5G `z¬z88J¿¹&ÏýA}P>÷yh]bÒJëŽ\¶lgjiÁ[e(+›P–0•Ä4¥¬<ƒ)+Lšk/Ò§®3*îÇœH)QZrÔéNõímß¶­­6¿Óa½äÝ¥éîäæÒ›'öÈõÎ ?—ûö³¬Ñ´í…£÷ž…£»<àhÒÈnÞŽ[­¸ ##Ÿ!¢]é©Exr3Еå3¥¬Ài^ ÑN¬e}Sõüä¨B4“¡
- `òô+âÜšøØañÜSòý=X6+þŠ`*¸‡Aîhm€z|ŽOºÄ$S…(|RrÔœvTÝQÖNÕ¥nÊ•£Tä*,€=o‚§T¬ä¨>3õÌÚƒé$8´¦ÍNÌ—oô¹7÷;B¬Ë·NÉÿ±_¯=r[e
-COe•JDážÂ®#oyù
-=
-޲f5^qãUwp+st^³qTŸ­‹Pˆ’1utã™:ºÅz Ká­;©£vÉ«
-t´Ltt“ª¬j€ž¡…é#¢u Šó6ÛüìI~ù<ß»›ûß1Ã+¥4Fóò…#4ªä£/'<¢5‚¬G)#gÂTÊ\æÍ »ù¯ÿÆù,drŸ¹%½òv†³æ‚8û¢¸ýwþÍ}âðCâ ×4kÈjœiÝÌB7fzo„C -ù*cTUVÍP©)ŽŸy™ã“zà$G NbÆ¢¦FW7:ºÝO5ZiªŽjkè¨XEGµ:­ £ÞÒ\÷ÃÆ›§ê;lûç/è5WD%äsêè†3ut‹‡z- ÖÇtÔTu$D )•Ǭ!.j"]”‡è%|Ñ+¿ãoœåûîçÏ=É?5χMܧ¸”•)6Ç*Í«†éGêQ\$=JFRÚý<œ*«°™#Öñ[¼º1œ¹•‰¹YÕ„•¯X›åbõª8Œ/¿/íbv¨H•Yî§RŒÊè¤î”
-·tžvTSÇó”µ¼DiÈ/¥£r§–µN¹ÜqJÉQ³‰Ž-[o¢£|-wªÑ².8ºkÆþÙózÅ™:ºÙ™:ºÅŽR
-=ê@•òÌQ/±‡u†a5Ú¸5'9*¥[—££Z“ô—{«üü)~å"zäq¾kf(0éÎ<¼’!Ä+êÎSVÇüHˆªŽV†i’£f±$DS_½ôªÊ*Yµ42(7,ÑIˆUÛg_Ô#±ò>?÷¢h-ˆÃØcû5;`Ã;lNKÙ«F,^c3"ëKYŸ°Câ¥9GÉZš‘$íÑœ¦²Gi- µ¯Z u=JŽ–›v¹•:
-IJŽwÜáZÿæ\ïZãòKõÏm·þP·Ì©£›©£[<9G©G«Qè†÷¨DQ’©ÞæšU]Ã5}\Àu›M~æ8ï""úôA¾c 5Ÿ×t\S•J ÁWr´ÐË¡'GñQÒ£Ä$9*½W³pÀ2vãƒ)íþ¦PÌíŒW¬Ü” 7b厘Å\Äÿ"^ùð—Øhߨ‹ŠVª#ÐèÆ)™Eu(FUGÕf- Ô/FTö(,ÀQ
-VÈPÚ$Gá–5APš´GÉQ³]à(õhx{4X®õn`^:Yß³Ó~Ắ§‚NÝp¦Žnñ€£ oÞq´¦ŽR:š‹K°s¼PÇù”‹™f(hÚ0¢ÎbôÚËüÍWùW¾ÄŸ9Ìï›Åܤ©2$$8s
-Êýñ½KzOœ9š§Ï« šKÏBG/éQÕÅq ÇkR½-dUå“^¡[w˜.,P-¡Úõø<¾#.gÁªöôcìÏfò•Ú¬QFV+!ÞªUJ`\MÂUž—úæz”ìT)%>åÀ kÛ/³vê(ô( jvu»_ì¨Ñ²õ„RˆQpTkaF+n¸Rë\GG/ž¨ïýŒýü÷uM{t³3ut‹Gö(ç^Õ8Ì«ðÌÑ»ôhÎÑI‚J_sajxÑ|9²†Ø£ømô·+|ÿ—цƒ|Æ]>ga†Bq‚” )óF¸•Y û0°3’•azU÷åæ]zÅëz’£0ÒQšq>s;ŸA2§Ç*ýlªƒüŽr[ çø¨Ãy5pQâ!:
-¬VÜõE= ï²—iZ={)e44RX€—ªˆ)Š“•;ò0- oÄQI&
-*Q˜B†Âšu#tToƒ ºÑÁ­ôG5ÖÐQ³mkkأ㎶ÿ“:úàçíO+•¦Žnv¦Žnõ˜‘_
-—Vƒ0ô\{`3ß™C H‡?cf#-(¨…yZЗãÑ)o­Äàj:ƒ`6
-/¬ñ´qk:_[䯟áoýY|m¯øÖ!qόཌ: Sf¥º9ç¤Q_§“€tq­òØ
-dÖ5­ÔÓþª>¦™ö'µÝ;5m 91^a‡ÖpÆjV¨•}ÜÔ=ØdF
-9[ö¢º­^àúA J7ŽމÙYâgŽó¼Í< ž:ø_öëíGn«à¸}ì±=¶÷ÖMÅUPñÈM J[º¹”^Ò&¥ª" <
-]Xa•vÌ..=ÝOñjôØ„Ž@þë6ÿ[”ìñGØ'oaésx§ÞEÞHV”pu…n%ºåòUârÐÑ ¿|®pŒuãìc·pÔèa€6#¸Zv·pÖæzÕÑF5[UGµt”/Î¥íÓ3­ÓS¯¾äïúŒý«_èš’ÁÿÌëýõ^˜±£Û=ôÜQ×êÙZèj£zÔIë¥ZV½”[½Ä ’Y–4äóiÆÃeqðiqüˆ˜Û)}Pìðd².üUª÷ÑHøQMVd=ƒ)×mQå¨%…•äŽNŠ#-«§ì«w”Ú´˜ ÏQoÈ£í êè`•V4…ÑÖt7AJõêdz’ýýìÐ3ìCSì+÷²OŒEËx (Õ:ù¢Aj†¨©'‹m„ÕÜ£å%q¡GñcŸ oÁØíå=JŽÚ]tÔl=š=L¥©ö¨lŽ¢0k§fVNMýã°÷Nû—Ojrìè–gìè6`¬'—–ã(ÂG¡GÁQ/ÙÄÑAM•£N\|„58jGÜx…õ„äÝ‹üгâÍ×Ä—îî7{˜‰f"aà¥Ê¶rŒ^«£•Üý]|~ŠŽÚõƒ8pÔ 7A´²ö‚T¿p²jgßÇ~G³ìí{Ö £åî,·©¢p·c‰Â?&ˆ(Hé
-ñ¯‡Ù+¿g·ì`_½}xo±^n'œJa
-ò· ¥:š :jurGa­…[ä¨êQ³íȵj¢¤ëÿ¹zbêȼ¿ïûç?Õ„š1vtK3vt›GGµª£vÂ'ÒGQ«NÐÚU­O™B„Ö˜—OóùçøÂ1¾çVþð=bÚÂ}ŠEð ^Z©É2Š×Jé`›V„.öÓ¾Ý
-ËƒŽ–ÉT¬Ò•Æè ¥Ç…‰e‰z¥é{užýùûè,{ülSÙ.bc1À±Q_ÝBJñã £;ˬ–wè
-ÇìÕ»ø;VÊRƒfLö÷hÅQêÑZG£s³ÁÛ3—ßÄ=0g?ùã±£×0cG·y”£aˆŽ:ú(G¡G­~Dká,ß‚µ9êhÄrÚ–WÄ‹O‰Åã|ÿ?°‹O3n„Hi¸"<]¨Uò®J»ktÓ¯¨‡“£8wt"ÀuÑ£ÊÑ2¨¸&Gc”Å5Õn·èQÕ³eJÝÎJzª<-S
-‚š]7Á1zyqBbÂ(í.åUúù³ý»ÙGnBJá °¨>#Üñ5Ýæy½œÃa1šÉWÝ¡¡}'*uÜ,;šI t”ÎÃ­Š£Œíwb4<;ŸŸ¹ôìч÷Ø?û¡&¥z"íëÿCuãÏØÑmiñ„åŽ6¹£/59:êG¹£¸0²g­¯à¨“
-3‘V*[åÊÓÿÜ…Ž~Ðçé*—kÜ×…Ï„ã4eáh-YG9د•g¾kG¼AJ G«v–X%Gi@Ó‰¨ú\Z@*Ak)µúƒõá·^`ª“ `Ï/§ –¬²çÍŽýÝþ)öÀ{¿µ
-Ç DÔl­;)$)~ÅÈ-9Hi…Øò£ŽÒÛáùУlŽµŽŽfjªçXF¾Cw Ge«¯Gƒ3³É…™ G§þù²ÿè½öO¾ŽJ6îÑ-ÍØÑmž´Á¹™\^{½À1ÑQW‹›)÷’Q=ªU :q½¦°?iÀ¿m¹xZþýÒ9yÏâË{ùM&×Ö¹Ùã7ÛÜŒÐ3#BD˶ÈÊM)‘¡µ"G­d«Ž:Ý!I¤ú…“h'!Z©ÒŠ£0nrùù †À F’¬ÊWå(ÝÍé˜ ¢Ðš”›$ex•½ü{ý/ì¶O°{Øû<ÄÕ“H¶½)
-G­^MƒV­ JW7SÓ
-ÐQø/·7BS_£“è¨ÕA)­u‚¿•…oÕQ½UíÑt ¥=ÿÆÔëò¿¾ÏþÑcG¯aÆŽþÆäKËI{=ðž%COí$vEV“i¡Ž“ÑhGH£BT­aBâGXÀ1/ŵ+QÇ¥³âŧÄò¢Ø7§ÝûmšiÆZâ'ÉdŠ<[!¾ÙŽ!¹%б%o¤ù¢¼O››}«ö å[ÙÇ Pc­ ¿7"RwÚ…”
-;£° €¤+mêçOÖÀë•4_ O]rÔ
-;¼Å| πУV¢ÛÛÔM±)IJ'ì ÐÌ<³“ß2Ú¨X±A ð‘Fk¡”v6Y’‚¦ˆ(|p…5m‚£f†(Pj¬:fËÒ×-­ãˆUêÑéôât°0Û=3{éèÌkóßýšý½oéºÆñ—±s½œÞ 3vt›GZijðKWãN'ðlå(*HŽª€#G1zc§ù¨µ•ñé‹\Vtœf|Ê‹'Äü bá-ñÐÝÚ}·k^ªémÍ/FG›½ÊQz=–^­Ò³Ü‘›ö¨z°U/ª¶i‚Žºy"êÍN‰Âh$ò*²ê oÕ-Âgùq0ö
-:.æŽ9<ñÄcÎw¾Ž¦,’ÍëÿCuãÏØÑmÍJ¹=·Û¹£®7ÓÊ]RÙàÈ8
-F‚£Ê!»¤¬'CŠQø"0 ¦Njüì1ñ»gE÷ЏNì½M›14ÖÁñãìßÄ@€ãXa~µ#\ØÑ¨¡tx+³Éã<F³zs@M%å0øÚ¡Žª£µ¡9ÂËŠ¦Þ(G«ÖF3BÒfй ”‚—°^~›½ô4;wŒÝÿE¶ï.Tîfâb‚£°n„È$@HWâS1YnSUñI'AGR6[+5óU”šëÔµùN†hÑ£f “T_uaäª'Výôêdº=º£wföâØ£?ø¦óíÇt MðŸêõþ¡ºñgìè6´xÂ’¥•¢GsGádöX1$«$;R+É®Œ( üMÕ”ÂÕ_®¡D='▸󳣓š]Ѧ™Ö
-Ujÿ‡Îï¡_ÚIͪb”¨.®Õä,8]œ•G43µÏ§°àÔltø„Ç>«ºå ¥
-ÎåÓü¯xk‘¢»T¶JØ@G«‘b¤ÕI¡ÉsX´S¾:l[žªâñ<r£ÖÝT®|ëVAÖŠ‹·K-=­4FðV«ùDz‹”÷¨ðÏtûùèöóÔ…„¥VD¯ž¦oüB}B•Îí¢ð½µÐÑ *å-ØZÅÇ‹ŒÅE¤Í°Vmä3ß z+cFKà¬vQÐD«ÂQÖ‘‚Š1µ¦ÉZ}Gëèr-^1"ÇZàè–îµíοgoœØúÏ¿Mÿè6ÿ ‰xiðÓéîßTŸü™8:îa~ȼºã7½
-ëVTßÐÑÔ ¼cÑQHR™žùŽB€V)::­ÃŸ1¿q‰ÿå5^¿ÉŸûê ¥*J øÄ(¥ØˆtžtžêÝ -éΚI:zó]GÏ)ÆÊês„£ùêh~+++Îá@®Ô¹ èÈRG… j;•˜¤:
-Wƒî<ý.ýûAÌÓ§¿Fˆ!PŠ/'¥WØ)T\i…  E}ÂZÄ( ZééjÕGõfÖ Ѽ£²Gû”¦=ª¶˜Òž"K›È­i¥a„æµG?Úѹ0{ý8:úê÷õg÷¡£wÿvºGfâ蘇3?G;îÒjG-O5:©£p_IG5Ó@¦ãZõñ)P
-OE‰zM¾/ßóe®t0CMK”´±D…)iÿ%v
-Ga`ÁzŠá¥g‰s³µ88p$
-,ä†üuvÊ#ÌK˜è &©^ÐMr–·Ol€§p.¹z¡<Fó3/S0Ϥ|3ùtàåþü$K…
-A)M‘Úz±Gáj•˜ž=F_ÿ=ÝV£/ì#Ÿÿ|uR(T8Ô¤-Íò2D…£b ×±z)ŸNˆQ±0d²ÒIùŽZŽÁVÒµœÔQf§=š‹Ñ´G…£¼5Eê›é¨Só–¶ô®Ýß9?{í:ú“ûö‚£<VïþuOÌÄÑq ¹,6ü••Þ”ÕÕ"·FCÃK’Ô…¿oÝì ÉY ?™bSÃÃSU/¶8®©‹ HÒ)5¾ô~üæŸco%~i>~b„Áx À*4%‰NlS½Ÿgš¶=Åmù(”W.öâš×)
-8¡âPÈSÈ•s%ÂòCr³4@ew†h™>fa-—¡b!¬šÒÔT‡nfÔoÐSïÐÃèöäåyrÿª8´Æµ¸¡ÕB¦ÚŒ9à\
-*œe&¥ Äš‰U7Cb4Ÿ§ø7„ jMÃX1kMµp¶RMJq?ëH§e•š¬e*
-mV•ú”²T%Í*oVƒúÿÖŒ·°Ã>3{ãÄÖ“G¦ñcóɯ’H™8ºÞ™8:æ‰ôP1ƒÛ+~£Qê¨jâ ÉqcŒŽê=¤±FÑQÐÔŒÑQ”ôâÿ~¿ñÇ8vâçžBDaï¤Äê>ôŸDKä`¹[ëttMY‡9:pdØÛ š?KPZÚ™bÀÑQ4_¢¥Ý™u´…sÑQ¤Çe,ënfgžRÃ¥PœUŽo HR¿AÎ#oDÉ OÓOo¡~]›ŠÀNÆë¬â¦1Š-ÛÍê–9È'
-|jIY‚©ÂÑQt4ñ2q´iTšjµõ1UVªŠ:ê.ložCGßkúW¯²¯ÏMzôfâè˜G8ºÔôëõ^Íìê1:Ê\tÔêzŽ*Ìþ:¥U‚”ÂâúEDÑŠ+]| ¬…ý:6¨´ …§¥n}ì‘ȱBé°: èˆZ-vçÀ»”~Œñ8ª—å&4( VQ:Zmu€æAíအ]BáWBL¦(ñäè!òÎa²ó3ôE tF —±>+¾¦¶1FN Ît3P¥£¢G¨ÀgŽRÄR&©i§‚
-Da4/.?8*ÕíÌQ¾œö(8ê/ogz7¶Ûçg¯ßzæíé_ÿ”ÍíGïþít¯ÌÄÑ18JÌ`¹é/-¡£Œ»UÒïQ/W5z™£š‹XBJ(Q
-‚‚²°ÓˆðD#“ UØð\On÷vt—-žR<²f1§ŽgŽpT¬ûÇKMfpyȺ%|êl­%1ÊÛDuI…#¥ðk£ªÐ¦o¾Nÿu”>ö9º¶™¢—à(_AG³ÓPÁc½dŸÒμ£ýÉà@”azæÍb´è¨ìQpzÔ>¿íÃc3—ŽÕ~ó3ýñÇGY±»S}ògâ踇qAÝö{U£ktÔôC+ ¤G iJÉi ‹óâIDàüÖÞø+"® ++ ï ¥°N4ýUŽêCĦԚŽÊ=â],¿ÜÑa×_¯íèå³£^f’:o´ˆ¨&ØVHÒ5EJ½¤8“î”vÂB¬Ó#½ôt+ÂË‚¦»ðhÁÿÊeúîaúÞÛô‘ÒÓšsSÛH(íd×1zÌè yº¢h9:KÖ°H¼1:Hé*MƦ&=*>°.®Ù6µæ*G•ú¿ö(8êßšñnnw.Ü÷Á?6}t²öÛŸë_|dâèÌÄÑq ¹4Úèh…u Å­(a%DG™Ÿ:Ê|p4ЕP0Õˆ¹r“ó
-á§ó#yäðïÌóGä,âq‡×TN\n)œw9d+°ªûèh_ hÓ¬G%~ëÔk=¡)ۯȤŒ¨ÈS‘¼5‡\:WòY€ûƒ×›å)ÅN-/Îašº© ÅÍSjAïvñ?S% ´ß;°Ö:ð¥J+ ¥‡þDÏŸ s»è³OÒ5CˆWªv5ÓÅ‹ƒ£
-Ã"‚Ð0WN‘C¯¥Cžÿ&ùÂgÅB,(+ư¿u¯ÜQÃû?ûuþãÆYpü½æñ±Î±ÚPRÚ’ÐF¥¨B\?Uʡ҃¶ŠPÅ¿¢å' ÀH…ŠCMT¨ … QA)I¶M6Ù%»ªÈ^¾ç°çâyæ¿ÇŽVJ+Yz4z=gùøë<ÓuÌr[hdvçGÍÙ\Ì¡6ûÀ éÊrÑ)×”íQXd^úlù˜‚jLo¥P¢ã/É:ª·¦Í+—D¶•²Z ¨ôDT¨Ø¼ÊΞbÿ¹Ì¾ðiöÈC­Œ' kö‘RGDÌk¦ˆÂvÜQ¤DŽvK•ž0è(w,n[¬‹CÛ`g™·*¢U¡ƒ¥;Ò¨ÄÍ´G½ÃîÊ¡•?¸~©ü£çŒÇ£˜ÍuæŽîõÀ7!ÃoÚýímtÔˆ<+BG!ILä4 Cƒø<ÂånŠèúÛôôÏ)uè3OÒî¡f@™‹S¥4l#¥
-À—z‚c5Êߊ7ñ$:I§;
-Sr’g;#ŽÂU1{àhM&u@UŽBF´GÝõ;Ü«èèö•òóÏŠÇ¢ˆDÎiæŽîñÀ'81üŽã_¿î‹¸oFýrÔ_ˆ} åCð¸ÿ™1LìÄFLe„F^~“žzôÛO³{0ø.HmÄì„máÈLƒNBqÊ~¥cVMµÍÆèÀéiŽÊÞˆV/ -¸G37ÉËI c^¾˜ƒÑξ°§]Ì"ª*,s‡¬1<hÄ’ƒ‹²M“^Tàñ}!]¿HÏž¦[ëô‰‡ÙßÇ$j¡£P¤)Ëž4;UŒÂ(MEè8¦Ù„=Ü/Üì•  ¼›(6hg°î
-éÉÇØ‰£ÈOÜaV0ÉíèMTæÿ9Úׂ-ßÉXÃ"šx|nÅÑñÓAYfÜÊe®;ÕCØj& àÌùšqTm•£¼Žyj´¹ìÒ}Œ]»H_y‰º;ìñ/²ÏÝÏJv°YË})»’7βˆªŒiµòŽëÙqJT9
-[ÞÅUŽ&=ŠŽ’­ÔQÒJím,9WWÿRë¾[úÉs➣$&A$‚Û~G} fîè‘PÚvÂw×ýŠ„[$(EA9¬
-ç˜UçÊ{î ÕÑ9^™Y ³LNâ6û*ÓNÕ”‚£ DG+wéÁëY;O_þ [ìä£ì³'DÜÀÓòNržNÚ 0šÒ„UìQ8•„7u“ŸÎË^ÃÐQ´ÓÎTieÍ¡£¬ŽÒ­´GƒÔQ{{Ô¿^úñ³âΓ(ÆåÛ~G} fîèüçQ8½pu-4Ј"D²È
-ΟsaúâsÉÝâÒ©©£7•¤ÙëÈõhKËiÍÂct˜šnñ°×LÍ&)8Ê|‘pØÊ/»\tY%Æë¹òOöêK¸~âKìÁ‰¨Ž'amQöÐQ£‰ˆŸ€¨|ÂNt4×£úTŠA†ê*ÅEâ(o¡£0d(] Ûè(kT¢öh¸yÐ[_ê^FGãÒóßùPÚ£ð½é¶ßTïÿ™;ºÇð˜ËÈëGkkqäÅ%›,á–&£6«ttùoôìiSl’1j3Úû ÞQº”tüänÎQ"G9œY&oèè bžõ‹;0çh6:³êg³=š#’¾s¾à ÓO_¦#WmM¿àŒJÅdöW ˆfùÌFªÎV°êøì‘ùrµÓÕŽ«Èg B•BM‚¸ð÷«váuvö.à?àÞ#ø…Z O°¦â¤k¨RåèxDöhÎQÚD‡ŽÆ;©£l{è(ô¨{mɹ²xùµo¢£GBƒ€ÁרÛS½ÿgîè8JeìGdcƒÔwh…ÇVÈÑnà@0O@„,¿Áþðkj…ôäcìþ;ñ+úb7*iŠ…0É›±oœ# :CDͱúᜲ?‹¥&S;š]O Ó¢—.ÓbµƒÍôRp”}lyHxµ†í„)nSfäcÎÑ\bf#U E©é;ŠO zTÅ(
-jÓŠÇi×| £Í.žªÔÕ
-?pXG>!FÁÎ$Cq Ͷiµò=ª.)¹)»CG¡JQå(i÷(ßIío¡£½%{eñÒk–]úáwÅá%BH²yÎ4sG÷xB‡ŒN·¶Ùú*µÞù–ŽJîÊr$ˆ#Öγ—É‚&ûÖãì3÷ Úá.ÞZ0後weÙƒ»bHæèíŠ7ŒT_"¡£“z´ÔŸ¦iÎQµG½ÄpÒý0°žÑQ-W¶GÇD︦èèÛÿJÔŽr/¥T=ÌnÅ„“êzSð¨_«62g'¬œj [øŒÓhe%Öàtó=Zê¦=
-kHRXT}ÁÚx0l2ÖÙ›çØ¹ß³#ûèS_¥÷¥Qs(¨D85¥{T;*ìQ£ãŽœ´^àh¸yÐ[_ê\­ù¥|G:@bp”ÏiæŽîñ’öb*$µmöÎ*¼çË!¥žYã°W^}Kœù‹;ì™o°OÜ…™wÄIr¯â—³JOò–43ñ“½ç¥Sì¨YäÜDü&d‚£ÊNͰævŠ£ÙÄœ´g¼8 5-và4ƒ¡£“zTf*xä\Þ0á·)º#|jÁKØÂ'ZÖWµVýª?ÔrIЇu‡1š†i—ê6…Œ´ÕßOŠ6žs!b¤Ëþt4¥Ç#¥w/dù¬ºè¨ÑÄuÂjÞQáf¯ÿurŽ
-'u”·Ê¢:
-=JvÈ:
-{´£î5tzt‘ £‹5ÅA$æŽÎ4sG÷x8êSÆIÆ«+qc3®qºØ£×.ÊÓ/Háɧ¾"?ùÑäFMî=¸ÓT´˜éCÃìïíìwG¸…¦h4],µg¸uóš–ÜØtGp5£!Oãòi,u€fßNÇ( H[ÉV^^Ðù+§tù­´>µ£šUµPÏê…>F>åü*³¦êš4»i˜íô£!Tk-¥úS™ƒ-9øZõrµH"r¸N†›úÝ]ü0-GøÓFmöú+ì³ì»ÙײŽí·¢-ü0…ï%¬™^§è”Ì–%ÛÉg¨“ü“ˉ Fž²/ˬ…”nj*m{†ì–I³×k´^¥-tÔßÞü÷ó?öëþUŽ«ŒøÌ9Ïœ3ûvošÐÞ*-RŠ/…VllKME«b
-"¶þ"â#Š¥"Jûƒà? TKm+R•¶ic^۴ͱ)1¹¹w_fçmgvÆç™svæÌìÞ¼À…Xx8œ={ffwgÏg¾ç£5ÿý]§þÚýT[¾ôs¶c%Ëì4wÒÛ¾¢îˆZ:ºÍU8š3'cmlä§ç2³Ý×¼øïYñçß k,žû<|tHÖa5ÓÉϸ]œñy4¼A°k¼;ß©*læQå(Ž”ƒ‚TÝXnÓEe§é¨ˆŒh»…ñó#Øö‰Ã ²³
-ÎêŒe^ÆWª¾C1(¢¹GR½#ŠçWi¡3(¬1h+D¯ã¨Œ èKòu-æ]fo½ÆN`_|@|ï«âÓ.=d­åcܬP€.u†ä¨Я©•Åu†ä(ÕˆUa´á( ‹<Ú'G­ÒÑÉ¥{¢³kÞ©]'ßèÞ×#GW{äè2Þd-ÝæšBžCždä(çùñùÍ^벋§àõ߃ÿ üè;ðÈýpWγuÊ ÒŸ9Zê±'¬%¼Ò'˜
-;}žz¾ù$ÜÝñ†phãŠÈEa@Ž:=L!Tðs7ÜÒQBÔsù˜eƒëwœQÇÞìXˆè5rÔ £Ýä*9Ÿ[Üuâõîgv£½ÎÒÑ[¨¥£Û\ ›²Ö4)¶DàN××íGxÿöæ~^„ì…Ç$>YŸ ¯¦Üñm‘F:´ñ±|i2\W‚U«
-&ÒŽt±¸êXa5^:!Áܘµ}»Ò' ðÄìê2©5 " “ÉS™¤1GQ’ökQ»Ò­˜ fíÂr•£óRº³O¿ð­ù[_c>ÎiêØxw«·æ­9êFôµÙZ1µ¸;éMaó<¼úöÞ Øó|w¯Óↅ­|Ôa»@”U?kQBúä¨/pÔ*:è(Z›”GÑQÌ£v¿æèäÊÎôÒ½“3kÃ»Ž¿Öýì=òÅXÛ]:z µtt»K¤ Ox;ÉE:É3!­wßæ¿y†—àÙ¯ÃÓ_‚ìïÆ„¨ZÞíY 1u0nUެ§OQÅgI©H5¥£ØªÎBJÙX°ZxSŽVÔ:5¥¨0@¥xW•Öd-ìl‡ú´0¬]TM†¦Jß±½[±¤ÜÂV +ÃTFT/Õ43 êi×uTi/ÇÍsΣxóŽ.ªÊQU((‚ŠchOhäÊöÊ>¸xö>íìù²ts9õZ–GŽ‚‡.
-0EV D;ªò(ø”Gí¾v4¿¦µ78zôÕîÃ÷Ë_=Ϥ“匽ý+êN¨¥£Û\–ˆL—8w“ÌI™´._f¿~‰çcr—
-‚‘÷auJŠ8#îF:ð‰˜Þ*q
-,™
-Kˆjm©)vpB9Ó/¹mîÏö…F*EGU§
-©á,GUJ6G ¬%ÑF6Ý(:n}¸vôßïÔ`S­ÎîÀŽ×ÄnE‹¡6S³™GËk5mÄÓù æá ŒMG¹G|ª[®Z•Mñ:¾
-z.ŸßþŠøÚnÑš’‹ÙÀå>Vq G¥Ö”…ÑG1šŽfë6@GwØ×´£ÉÕÉÇäèà89ºûAùËŸ1`KGo¡–Žn{…Y'œ¶âLƼ‹‘ÔâœýŽ;
-Ëê€ÙG7] ô\W,¿Ê£ GÍ€»0¤Î;j†æëçQDáT—V‘ÿ øÓ¾»b¹OŠ7þ(¼Ëbï±ûs¢‰ÜÓŽÒý«M|Š9êxØ©9ªn?:Ê<r” ÈQRÕŽ®c$­>Ôyô‰ÏË_ü”1‹Í¥£7UKG·½Â´²•0kÅ©“r7K¦Ìaö…ı·„˜ˆF-.†N‚ki§_mÑ\Œ^ÓQUj!©„j:êÄ•µxHY2®ùZQê-Σh'Æ<•ôD±ìeDvBhØ6 2ñÓ/Ç:*ï°:9ŠejÝp´<sÙiù¶}ôm}žBi\TÞ‰òv˜·ªnL},5h¶jŽ/H»µ^8jº8ï¨ÖŒ,ûÊ×ÒÑ­«rT==•¦ŠRS…€ØkÇîN¹û~ëÆëâ™§Äãá=Æ[¨ï½”N‚5G±Ø°æ¨=¢ò!9ŠemôØæŠ½±ÃºŠŽv³ÍîäÊÎôÒ½á”Gý¥ûäC䨕e_:z³µtt›+é¤NZÙTLs‘gÜžZö4çÀ¬óçà_ï@8„»{ж€Ç" ¨àf´Hh+æÓÀ cÁÂ–åµ lñ€:ØbßSËü–Z'"R«EkZàZpë±dHñÃ\ʪ^:£*ÎuCmQçñΈ·u£<J«=&Gq7¢g±¹¬±W 5K±"²Ý¨[ÉZ¾¬òdTùbꆹÖ>ôÏf5ñ/3¯ÄG€¬mó’ó%g¹³D±èHwX#p!®f]”Añ$ªÊiÜ lQ‰Y¢‡Hg|J÷88i;^;ÛpWm÷ôA±ÿeaáûÏÀØþ€C
-­¬=p[xËFê)LŽ:CÅjñ#Fú~££vŸþ0ê°~'ßìZý¢”Õy4ýx-8½6~oס}ݧu^ø‰e¡ X2™ÞîuGÔÒÑm®ÄÉIˆb¿p4Ÿ2¢4I-×µ.\`GÁ•‹Ð±a­GÛµ¤Oì9^Çu\¿'†ô_gý6øÒI%$Ò
-
-8}¢‹’O¤šŠOl›î j/PÇ’’OF1¥Pú µ/ª£mcGojé-g¼˜ÌÆà‚¤hDX!hÂÙ”1l¦Du ̵öÁÔV‚–p6-e53/¾[|PWÏ©QÚˆ¡óŽ.œ³µ£šRrÔŸQ럯üÕ/‹y3e+l[}7Š3GÅßö‰É&üðYþ…8O ‰v‚5Š¡
-Qµ‰AD‹Rñ ¤ÛŒ7Û’£ˆ(ÿ-«¿ØQÿ}rôðþî·sžÿ±eYiÆ“\$™¸ý‹êÿ¿–Žns%Ž=åÄgÔŽRq¥,·-Ïc¼'ƒ¿.îrDÏê¯#Ç=1X«­Áª;èñÍžÝ'Gó€qˉˆRl­qáh$-ŸàTvb+&ÅΣ͟O±ßÌ£¸´ˆØñLD¿áJð°„Ok²H;´VÕ¢uꫵbò$Â"\Eúå9Ídh:*çΠ©ö¸}àÍŽ–§3m°j5íÙ£A¤KÞHÊF
-ލaeöÔ2C´@°AmºBþÑaéåJÉxÅJ´*æ.‡Ñ¥+{ówk€•Q!½`t¬«¿Z4aY£´ƒÌËJÇIµø”ìlÊ iÓ¡§ Ûj®Ÿ6,3F ‹.~µÜG#õØ:xúüs}ÎÓ_û¢|ôa9H¯v"™¯å¶Kô²B´rtv)}G…¿à(뢣EÁQÿ-tô™/©ŸüpãèG«£÷º¤È3¤”-"šË4SiªS)ÕÚ(r–Oåí÷xûPv?Tþ±éšÉ@‰ÊFj ˆn
-…@Š åÆ-gÔÒAKù-9¨
-R¬êlËö¶êíðÎŽìíèƒò-,0Ñ…ÙÌ1 mè‘¡£ÊµU£ ðU!.
-ä(Iк²ZÃõŽêd.b•ZQÛì•¶žQ²Ä“ $»öÚIì5©nÞÞµ¡SÆÏWKÍÍ ¿eýPúžÞkÉ\‡ë2¢u)î?6Dꨈ=ªb€a
-ð³Fª› Þ·ö/YŸØÑž’ìJ5…`
-“H>Äè)"r°Ä
-µGï²6Žþ¿j&hõç˜ÊÌ0³BgSžLÍ´eN-OÜN • }e"5$<…¯†'b’ˆa¤zmÝ9ÔA×ò¬¨ãD‡ö¸mO{4Qdzҵ ¯z„LòÀSC7ï¶Ì L…ŸR¢…U¸Â0¸ª°Z*pEPrT‘FŽCC¾¬NºPóÚÅ:ÈQCD¨’®âbÓ¿š8«Î¹lJ”RZ•‘f¿}­B®fR® JUwÞ}¯+ôŠ 4mýW1–ñ*œø±J½£Ô®­÷2hÐ-º®5tyßMÜÂ3î+?3ÿò†øÌ£ìé/‹‡Ïʤ¿ËÃúÇáxø.åÌQŽ1”¡£C{ø§
-g•ÒÓT ¦ XåØ/ì)ž2
-U;
-ˆš+FÒUͬQåø¦?\£)ÎVpRÕŽ‚Áìêþ²aèåÄdc“'x5b,hC£ªs©Övb,ùÒÌeCœ“&§×©è­™*vy¸Tåç»lg¥¥ÆÑTÆAÑ?ØÚ²c×»Öäs§]óÚeùǫ쳉 çåÇLùè( æó(í‰Õ<ä(Ì£t´èTy”Íz£½»7^ñ¾û õýç+Ga‹/ÌÓ^QBm½/
-r*x Ê•nss4õÆ™;Î=¨Iî Í©N ’+ÖÜàyÁYV°i&òL$±‘$Æ`À»Çrp,ý6 ²Âò6|\Ò2„ºãDg¼p×ì<¤Ûȧ5Æü
-«—1LAK ¨íŠάؤN%‹-Z:ƃ&,N V1­²{è Šb,ZÞGàæ«
-¾)†ñ:߀GTÐÅ,h×oÑøÕ‚õ ug=¸î¼COóÖp5.gÐ;DÒ:â‡T©”>Sh³>–®Îèëê/­·þ ?ÿ˜>ÿ¹-!¶Vc(È ô:}O`£²¿Å:P¸Wã%n1ð’Ã3“÷Ïÿ½×¾¾û÷ßx/^TŸ5Àf¥©Jó£wQGï‹"G©è6×ãÔ™d6Z!š•¬L`H-ÀQYeå¢( ÆYƒõ¿d,“PÝ‚ØjúÚþm7¸åÅÿmeGP;“0°Z –ŽñjO\sŒm5ÂG ¯Zf‚d€M×3 RûxÜ„@ 6ñIëŸcrͨ¡žÖ^Ð:¯à˜9jExÕAUÔnz@Æ«û `µy å*ow¨µšÖŽ®Nr½Ký5Õ<lÂåZP—4­á\‚¶ž„ÑNFÒçhô{l%mëÊ/ôÍëú‰Oë¯<á<$œé>ha
- Òk’¨a ƒ®÷­îm3j›~™YÃc3˜Å¬ß´
-Óe¶ÚÖÔu$S‡xd´†[²·Í·uwÛêoëÞ–€óbI,¹`–#Ë3%¾«Þ¢w¥ßd$Ê£ä‘I –©tAVèàË®¼Ú
- ⋾ꋾT4‰Œˆ¢¨e1¨»’ìÍìîÙsæÚÝ3ÓÓÓ=]]þ~]}zû\v9°ÙÀ,_Šêšê¹í™O{…µê¬ÐàZlUd×ʇT‹µµU…eÈ*Ѥ,X™Ù*µW‘ìxl§±íÅù*Yèª(à‹Ž»ìYàçÝ`½ã.vD¼CÇ;ö &]¹V‚ák,²lÐ8 Q W l‡G£ˆ+k¬Iݲš>fzWûN·m ýÕËõR{•/hÛ²¶;(àÚÞÙ¦÷äº<ê_-ßü>=xyÈÈÈ#R> ¤šø5_Ms
-,ÂÄšV
-‡½)ýÃËò¿{Ÿú0Rä^¶‡e´yE
-Ñ`¥º
-¬ŠÙwö–ŸîûÓîjè/îzÖíd]?íòyÀA /0vî2tÔwÒÀ^å´ëÌ»b‰{@V!à«H}kÛ`´â{^@—5ÜB€[Sd!Ü8Ú4³¶.Çq2óW]NÙïgžqîÁ"6OkÞö‘×}°µÍ†#Ÿ”ãwá«Ji.:ðNÂëÞï_òn½Ž”>ýQ<¬mj+„|§tvÈQè£à(ôTè£ÆQè£w_ÜøKð•/ðgŸ&%Á>ºuô”Ù:úhj¨™hç躮;%ÎM
-§Üˆ:ÊÕ9Çlœ2‡uYl|L&ñѼÚYz8Éxuh£Ê´j¨EžI%79hÀÚYÑVU0µ¶³…mvòÑm1¹åÆ»b>«©X‡v¹¶IÎI&èZð+r,¦
-œ¨ð$°æ0â"Ø ¿[
-1UJ*hj/k_anÍëþ
-‡4ôéK?A0ªrZ#zÔCÃ6ÃàqâÎöáqž›í“ ¬ª^{ϽsYtrݼ_ncÙ¨Ütж£f"W~¾çûkü€å¯2†UxŸÃÿb+ozO}ÄûÄ{‘R5F¡•2Ô¼½ºÒIÝGÁQxHÍjG“+ç÷þ6¸{)øú—ø“ ÿý6ÜÜêíþ%¼#²uôâyé8›¬•ASK¡
-`²R3·Ø†°‚²’ásea`žk<Ôv=/
-pN‚ ÑY¦RØO씚t•bµ•'3ì©ñ0ocâÝ ºãÍ÷=:d^vì¤#Öxy ×X[!&æ}ûôÇ?¬5F¬AÔö€.0‡èmN9B©iuÇë0?&¢9Iýü¦¶ží„fü€À Î´[
-9Kðýõõ¤oÇ=¾ìY1Îy|Nïžµ'îØa
-eÕk±œñ¨#ç}>êÙ@ÔcÀuLG†–¹
-–"ö† Þ„„
-!Tñ¸àŽ
-õŽ‹↻"ñ%¨Šª½
-‹u–÷ GAÊ,Ïp4SvU<ëÄàÛ’OÂ(FŸugV‚®UQÙ‡‡
-”Š„ñDÒÜH˜cD4Œ )…Àg¢®
-ŽRžÕÐÌÑD`1…JJà/SÃÆ #¨ …I|âY•;iLh
-T2–’´øŒ‚½ œ¶zUŠ,S¹†ž bÃ¥ ¼$'QD¤dá‚-f|Ô=1ö´þ¾t´àÈCƒÏ ±(+Ó2›”ÅÌ.M­Ò±¥MŠÂ
-|²®[
-\>¨«ØV1¢StVê¡Ê"ë©Y°êAÄç±ÈŽŠ£ÌLj ˜Ï/ÂgWҵŷ…gð™Ï
-_íÂlÝäœ9ÛQ¢$)“ GG‰AGPCÃADÓ¬^J†W€’3„3Nñd’*”P<_
-š¢£0'ÙiÂPOU\€8cÛ]Æê25æIyNÌeªGT‹àµ¡´IÖ\¸z(&}áÿMìÁ1n£¦Q¿ze˜¥¥m;šïªWꥑkø µë
-*0ÃŽbå¾£xH˜É& _¹+3_q‚ˆfGóõùF>Ÿ¥X¢#‹+t\9…hN¦6GJQh¢¹£ÐGõ¹µl[×^·_}ѶCû— {¶ð›Ç7êÉatš‹ÝÖìýÖâzó//Õ¾üéÊ/~Æ“8…ûw˜•ð½ÇܦÞK6ŽnrÎÜ¥þ/{G˜¤2-½-kßð%t}[*Å×R¢­E® ŒJ
-b§
-û5Å_ñ\àŠE¶@:EHs|{¹opÕyã7Nyâ|ý³N‹9´W_Üj¦­x÷bx­5ýÇö?_vÕQíùç”Ï\¢QÇ —ŠTÊ2bÅ=Üä?gãè&çÌÿÑѳL½_GSµp6 °‘¥zN,4߬/g¬B(') J üÃî±åœ-ŽÙh€šzi~ewµ…o$1ï¢XæÂ®.¡¶BUÝ2ûªý ñÎVÉ5ÁEÔN  •:´ƒEVõ±òþÇ¥
-몆® šOæM·@è‚âlT£'‚æd"ŸÃ
-¥½« »t`SN´Ó.fç çµ_;Fà|õ ÷1›h²ß½sQÙkíü¡yëÍêŸ1Ÿ~J™Ï©ÐcªÉ¾Iè’Rf·ñAÂlÝäáÌ ¨ü>…þ”Û™pÊÑÕn‚âf ò(Qªæ‘$K*$ aI‚¼’("³ ^ypÓÞ´æûöô¦3Ýq“}—wõBÕ³4µ‰£O1pDßÕú®êag…ð.vÕþÙ”R•'XÒAá¨:­’A±»ê à(š40ɰ@ôÄQlϲc‘¾UYÚQÛùÛo÷^vÙ‘û¹­ú§ìíðÆÅt÷âî+­½?»OÑüÑ3<‰éx––m¼’K¢oÊè}dãè&GÔ³‰„ùÿîh"Öu¼ë $š„1E&ㄵ•¨KZBJ!T/L¥Z$YD´<`ª$“Â(H“$aqÄŽ'|ÔÞÖÁ¾”‡·Ìeë  "B}¬F*°ª]ÃÏÍL-
-D¡¶B[e=Gñ0à.Š›müÈÊ+*;DGózª tU¿ª¬5TZ4Ú¼Úæó¶<„ŸÄáž{ãªûÚ ®è×/_hnÉVðnëÝ+Í/|²ò“gÅV=]À]1RøµBŠÏ¸ùƃÿd<
-Ù8ºÉÃõ.PÞ££«ä ®kZSqöé±"™.¡öb(¥dE+Í‹),ÀRŒš&TIb‚î(¯"йd0Ï¡¶Â!G|6Ô†mcÖ)OÛåÞæø{á²mEGVêaaÕǶØvˆmUž4׬³f͵!: ~Ô`m‹.«t\1¨±“òʰˢ²Ú ¦ô
-qAâ<JÖzÉ!
-M:Nrè$m¼Hø¡ûÑ›î_¯ÔI§é.›óÝú—¯þ›ÝrÙmä¸ÂpUuõU¤.Ö¨±å1$á ðÆÉ>«l¼4 AMÖÉå1üÉ&»ž±¥áh8’HQR”ØÝUurN7%ScŽl% •€C| Š5ÕÅbϯ¯ÿ¿ÿ%ù  ø“!Á=[t6ÈÈØâÝXìúÌ»`2~ð.Þ7£øw#ÑÅqó&šo}3º¶#8.PYÝ ¤UšiÀ4˜{¬‚J€ @„õ{à-¦¶*¥R $ˆªÐ³q<;'òëñ^zÒKÇý•ÙÑÊøuÛž´Ýéš<[Ó“h²‘^nÄÉEŽ}œ«A ·‚#BcI‘zI–GdÊp°æñÑfð†¼‹„‡]Ýïªýšþ–:Ü*_â…[âÍVÕC}æå«üÕ¿ò¯ÿѹêmüíOí¿~™tÚ²´ø)UÛÌ„ 2,è`%þ:R)Ääׇ‡÷°G?ˆÞY5ïQt$t±˜Þu±§Ö
-, ‚Í\_‰¸ZW.-*…Å,T}¡Ò¢yY«ª™®¦úd¢áAt|ŒúÉéAv1Ȫól:h‹óvx¹–kÑt#8íD§tœ§çytŒîDƒ’2ãA7:膯·ôþûáK"êzïýàûýÝŽx±îïˆÝ÷Üî¶ÝÛv½­Ùn>y‘÷þÙ™îm|õÇìÏ_„Z´4¹RÚÔˆÔàý©$=TÊ4á>ú³`2~-1hÃÿ˜ÑÆ8©Z-”TÒ§&[ PëSD¤L¡ Ñ…DŽ¡žoÀ5n%âùžÍ¡þ€ pÉÔ­Ž¡3¶ëS»R¸Ø¨¤0´n[ë9¢Úê„“x
-Å¥(˨„•R¶±©—&¡ÿ
-é@M§ÑÙ€ä:ħoâóƒt¸»rÑo{«EÝ> †ëp´^ì¯ÊÓöºl?Ñ­<ÉžåÉ'E¿þE”gÝÅ5P—ÍÜÊÌf3“±Gÿ/üÉ(Ã,ÇŸŒÞíQ*”˸mÙk•ºx±¿ÞøÕ¸dl×/`í­NmëÊe…H‰
-oDbÏ œÒN(¯²E¡Š+uu¡/ÏÂéIh¦D1³0ÜÞ ×ÛA»(%­
- VÙº—Ê@ŠÅÚxý]ë3­›ñj1s/üÉ(Ã,ÇŸŒÞn–w×f²úGÿÚè3²ËÄŒò3N“\0$hSÕ[¡>qÞäÑ\ßLÎÚagfX_3Úö
-—gVaãÔ¶Rt6j¥x†ùZê{æø“Q†YŽ?½Ó£ å²EE“?±öÅysµ¢€Ø%±Ï‚”‚^X-Á*
- *¦ê/mzjóQ:S~{1þd”a–ãOFïçÑ[Do¯Çž
-Ñ[;"hÌÒk]Fô"êýç$}ÄyPÆ(£S\Ic§+WPS¬¤XY\úD›B
-q
-/GS0 gs
-283 0 0 301 247.3291016 320.6708984 cm
-/Im0 Do
-Q
- endstream endobj 771 0 obj <</Subtype/Form/Length 3898/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Group 768 0 R/Resources<</ExtGState<</GS0 770 0 R>>>>/BBox[291.387 581.187 462.953 378.781]>>stream
-0.592 0.753 0.141 rg
-1 i
-/GS0 gs
-q 1 0 0 1 314.416 463.6797 cm
-0 0 m
--22.574 5.081 l
--10.717 57.775 l
-11.858 52.694 l
-h
-f
-Q
-0.749 0.145 0.733 rg
-q 1 0 0 1 314.2578 515.6738 cm
-0 0 m
-h
-f
-Q
-0.592 0.753 0.141 rg
-q 1 0 0 1 314.0254 462.3418 cm
-0 0 m
--1.264 -5.624 -7.303 -9.058 -13.496 -7.662 c
--19.678 -6.267 -23.669 -0.579 -22.405 5.045 c
--21.142 10.668 -15.097 14.102 -8.909 12.706 c
--2.722 11.311 1.265 5.624 0 0 c
-f
-Q
-q 1 0 0 1 326.0322 515.7002 cm
-0 0 m
--1.265 -5.624 -7.304 -9.052 -13.491 -7.662 c
--19.679 -6.271 -23.67 -0.585 -22.401 5.044 c
--21.138 10.668 -15.097 14.097 -8.905 12.706 c
--2.723 11.315 1.269 5.624 0 0 c
-f
-Q
-q 1 0 0 1 451.0889 432.6533 cm
-0 0 m
--22.574 5.076 l
--10.716 57.771 l
-11.864 52.689 l
-h
-f
-Q
-0.749 0.145 0.733 rg
-q 1 0 0 1 450.9365 484.6426 cm
-0 0 m
-h
-f
-Q
-0.592 0.753 0.141 rg
-q 1 0 0 1 450.6992 431.3105 cm
-0 0 m
--1.264 -5.624 -7.309 -9.052 -13.491 -7.662 c
--19.678 -6.271 -23.67 -0.579 -22.406 5.045 c
--21.137 10.668 -15.097 14.097 -8.909 12.706 c
--2.723 11.316 1.27 5.629 0 0 c
-f
-Q
-q 1 0 0 1 462.7109 484.6689 cm
-0 0 m
--1.27 -5.624 -7.31 -9.052 -13.497 -7.662 c
--19.684 -6.267 -23.67 -0.579 -22.406 5.044 c
--21.143 10.668 -15.098 14.102 -8.91 12.711 c
--2.723 11.315 1.264 5.624 0 0 c
-f
-Q
-q 1 0 0 1 350.8867 396.9824 cm
-0 0 m
--22.574 5.087 l
--10.716 57.776 l
-11.858 52.7 l
-h
-f
-Q
-0.749 0.145 0.733 rg
-q 1 0 0 1 350.7236 448.9775 cm
-0 0 m
-h
-f
-Q
-0.592 0.753 0.141 rg
-q 1 0 0 1 350.4971 395.6455 cm
-0 0 m
--1.27 -5.624 -7.31 -9.058 -13.496 -7.662 c
--19.684 -6.271 -23.675 -0.579 -22.406 5.044 c
--21.143 10.668 -15.098 14.102 -8.915 12.706 c
--2.723 11.311 1.264 5.624 0 0 c
-f
-Q
-0.749 0.145 0.733 rg
-q 1 0 0 1 362.5029 449.0039 cm
-0 0 m
--1.264 -5.624 -7.31 -9.053 -13.491 -7.662 c
--19.684 -6.271 -23.67 -0.585 -22.406 5.039 c
--21.137 10.668 -15.098 14.096 -8.91 12.706 c
--2.723 11.315 1.269 5.623 0 0 c
-f
-Q
-0.592 0.753 0.141 rg
-q 1 0 0 1 390.3906 388.0938 cm
-0 0 m
--22.575 5.082 l
--10.716 57.776 l
-11.863 52.695 l
-h
-f
-Q
-0.749 0.145 0.733 rg
-q 1 0 0 1 390.2373 440.083 cm
-0 0 m
-h
-f
-Q
-0.592 0.753 0.141 rg
-q 1 0 0 1 390.001 386.7568 cm
-0 0 m
--1.27 -5.624 -7.31 -9.058 -13.496 -7.667 c
--19.679 -6.277 -23.67 -0.585 -22.406 5.045 c
--21.137 10.668 -15.098 14.091 -8.91 12.701 c
--2.723 11.311 1.269 5.624 0 0 c
-f
-Q
-0.749 0.145 0.733 rg
-q 1 0 0 1 402.0117 440.1152 cm
-0 0 m
--1.269 -5.63 -7.309 -9.058 -13.496 -7.662 c
--19.684 -6.271 -23.675 -0.585 -22.405 5.039 c
--21.142 10.663 -15.103 14.096 -8.915 12.706 c
--2.723 11.311 1.264 5.623 0 0 c
-f
-Q
-0.592 0.753 0.141 rg
-q 1 0 0 1 396.7148 562.3232 cm
-0 0 m
--25.313 5.697 -50.125 -5.692 -60.314 -26.113 c
--62.61 -36.313 l
-42.305 -59.919 l
-48.003 -33.322 29.156 -6.562 0 0 c
-f
-Q
-1 1 1 rg
-q 1 0 0 1 371.6279 541.8232 cm
-0 0 m
--0.579 -2.549 -3.111 -4.149 -5.66 -3.581 c
--8.209 -3.001 -9.815 -0.469 -9.241 2.085 c
--8.662 4.634 -6.129 6.235 -3.586 5.661 c
--1.031 5.087 0.569 2.554 0 0 c
-f
-Q
-q 1 0 0 1 419.7363 530.46 cm
-0 0 m
--0.574 -2.549 -3.106 -4.155 -5.655 -3.581 c
--8.204 -3.002 -9.81 -0.474 -9.236 2.074 c
--8.662 4.628 -6.129 6.229 -3.581 5.655 c
--1.032 5.087 0.574 2.549 0 0 c
-f
-Q
-0.592 0.753 0.141 rg
-q 1 0 0 1 376.0195 557.3467 cm
-0 0 m
-0.38 -1.095 -0.031 -2.232 -0.921 -2.549 c
--1.811 -2.859 -2.843 -2.222 -3.232 -1.127 c
--11.042 21.211 l
--11.427 22.306 -11.016 23.448 -10.12 23.76 c
--9.235 24.075 -8.198 23.438 -7.813 22.338 c
-h
-f
-Q
-q 1 0 0 1 432.875 563.2764 cm
-0 0 m
-0.815 0.832 0.932 2.032 0.263 2.701 c
--0.411 3.359 -1.617 3.233 -2.434 2.401 c
--19.063 -14.429 l
--19.879 -15.261 -20 -16.466 -19.326 -17.135 c
--18.657 -17.793 -17.451 -17.661 -16.63 -16.835 c
-h
-f
-Q
-q 1 0 0 1 419.0518 417.2461 cm
-0 0 m
--0.938 -4.166 -4.592 -6.889 -8.172 -6.082 c
--99.887 14.56 l
--103.462 15.365 -105.6 19.388 -104.668 23.554 c
--91.661 81.335 l
--90.724 85.494 -87.069 88.223 -83.488 87.411 c
-8.23 66.77 l
-11.806 65.969 13.944 61.946 13.007 57.781 c
-h
-f
-Q
-q 1 0 0 1 428.209 457.918 cm
-0 0 m
--104.668 23.56 l
--95.537 64.127 l
-9.131 40.568 l
-h
-f
-Q
- endstream endobj 777 0 obj <</Subtype/Form/Length 305/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Group 774 0 R/Resources<</ExtGState<</GS0 770 0 R>>>>/BBox[261.051 585.308 560.602 555.632]>>stream
-0 G
-1 i 5.158 w 4 M 0 j 0 J []0 d
-/GS0 gs
-q 1 0 0 1 262.8428 563.6289 cm
-0 0 m
-8.12 7.841 17.83 13.181 29.683 14.781 c
-50.398 17.577 67.696 12.316 87.58 7.114 c
-124.361 -2.512 163.249 -13.37 199.899 3.049 c
-216.818 10.632 235.754 17.262 253.595 18.931 c
-268.944 20.363 283.878 12.406 296.595 5.972 c
-S
-Q
- endstream endobj 783 0 obj <</Subtype/Form/Length 308/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Group 780 0 R/Resources<</ExtGState<</GS0 770 0 R>>>>/BBox[249.381 547.932 548.934 518.255]>>stream
-0 G
-1 i 5.158 w 4 M 0 j 0 J []0 d
-/GS0 gs
-q 1 0 0 1 251.1738 526.2471 cm
-0 0 m
-8.119 7.847 17.835 13.186 29.688 14.786 c
-50.404 17.583 67.702 12.322 87.58 7.119 c
-124.361 -2.507 163.255 -13.364 199.899 3.055 c
-216.818 10.637 235.759 17.267 253.595 18.936 c
-268.949 20.373 283.883 12.411 296.595 5.977 c
-S
-Q
- endstream endobj 789 0 obj <</Subtype/Form/Length 308/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Group 786 0 R/Resources<</ExtGState<</GS0 770 0 R>>>>/BBox[237.725 514.422 537.275 484.744]>>stream
-0 G
-1 i 5.158 w 4 M 0 j 0 J []0 d
-/GS0 gs
-q 1 0 0 1 239.5156 492.7461 cm
-0 0 m
-8.119 7.836 17.835 13.181 29.688 14.781 c
-50.398 17.577 67.696 12.316 87.58 7.114 c
-124.367 -2.517 163.255 -13.375 199.899 3.044 c
-216.818 10.627 235.754 17.262 253.594 18.926 c
-268.949 20.368 283.883 12.406 296.595 5.972 c
-S
-Q
- endstream endobj 795 0 obj <</Subtype/Form/Length 304/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Group 792 0 R/Resources<</ExtGState<</GS0 770 0 R>>>>/BBox[224.77 475.759 524.32 446.083]>>stream
-0 G
-1 i 5.158 w 4 M 0 j 0 J []0 d
-/GS0 gs
-q 1 0 0 1 226.5615 454.0801 cm
-0 0 m
-8.114 7.84 17.835 13.18 29.683 14.78 c
-50.398 17.577 67.696 12.316 87.575 7.113 c
-124.361 -2.512 163.255 -13.37 199.895 3.049 c
-216.813 10.631 235.754 17.261 253.595 18.93 c
-268.939 20.367 283.878 12.406 296.595 5.971 c
-S
-Q
- endstream endobj 801 0 obj <</Subtype/Form/Length 306/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Group 798 0 R/Resources<</ExtGState<</GS0 770 0 R>>>>/BBox[210.521 437.097 510.071 407.421]>>stream
-0 G
-1 i 5.158 w 4 M 0 j 0 J []0 d
-/GS0 gs
-q 1 0 0 1 212.3125 415.4131 cm
-0 0 m
-8.119 7.846 17.835 13.186 29.688 14.786 c
-50.404 17.582 67.702 12.322 87.58 7.119 c
-124.361 -2.507 163.249 -13.364 199.894 3.054 c
-216.818 10.637 235.759 17.267 253.6 18.936 c
-268.944 20.368 283.878 12.411 296.595 5.977 c
-S
-Q
- endstream endobj 807 0 obj <</Subtype/Form/Length 307/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Group 804 0 R/Resources<</ExtGState<</GS0 770 0 R>>>>/BBox[205.302 398.421 504.853 368.742]>>stream
-0 G
-1 i 5.158 w 4 M 0 j 0 J []0 d
-/GS0 gs
-q 1 0 0 1 207.0938 376.7412 cm
-0 0 m
-8.12 7.841 17.835 13.181 29.684 14.781 c
-50.398 17.577 67.697 12.316 87.58 7.119 c
-124.362 -2.512 163.255 -13.375 199.899 3.049 c
-216.818 10.632 235.754 17.261 253.595 18.931 c
-268.944 20.368 283.878 12.406 296.595 5.972 c
-S
-Q
- endstream endobj 813 0 obj <</Subtype/Form/Length 3247/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Group 810 0 R/Resources<</ExtGState<</GS0 770 0 R>>>>/BBox[233.547 224.975 527.515 -126.011]>>stream
-0.592 0.753 0.141 rg
-1 i
-/GS0 gs
-q 1 0 0 1 275.1919 -1.8984 cm
-0 0 m
--41.645 0.037 l
--41.562 97.242 l
-0.083 97.206 l
-h
-f
-Q
-0.749 0.145 0.733 rg
-q 1 0 0 1 254.4473 89.3467 cm
-0 0 m
-h
-f
-Q
-0.592 0.753 0.141 rg
-q 1 0 0 1 275.0317 -4.4023 cm
-0 0 m
--0.005 -10.373 -9.26 -18.781 -20.686 -18.768 c
--32.09 -18.75 -41.338 -10.333 -41.333 0.042 c
--41.327 10.413 -32.063 18.822 -20.647 18.807 c
--9.232 18.793 0.007 10.375 0 0 c
-f
-Q
-q 1 0 0 1 275.1143 94.0293 cm
-0 0 m
--0.007 -10.375 -9.264 -18.771 -20.675 -18.767 c
--32.09 -18.76 -41.337 -10.345 -41.325 0.041 c
--41.319 10.413 -32.061 18.813 -20.64 18.808 c
--9.236 18.798 0.014 10.375 0 0 c
-f
-Q
-q 1 0 0 1 527.4189 -2.5889 cm
-0 0 m
--41.641 0.028 l
--41.558 97.235 l
-0.096 97.2 l
-h
-f
-Q
-0.749 0.145 0.733 rg
-q 1 0 0 1 506.6875 88.6514 cm
-0 0 m
-h
-f
-Q
-0.592 0.753 0.141 rg
-q 1 0 0 1 527.2637 -5.1006 cm
-0 0 m
--0.006 -10.374 -9.271 -18.771 -20.676 -18.765 c
--32.088 -18.758 -41.339 -10.334 -41.334 0.041 c
--41.318 10.415 -32.061 18.814 -20.648 18.808 c
--9.236 18.803 0.014 10.386 0 0 c
-f
-Q
-q 1 0 0 1 527.3545 93.332 cm
-0 0 m
--0.016 -10.375 -9.272 -18.772 -20.686 -18.767 c
--32.1 -18.753 -41.338 -10.332 -41.334 0.038 c
--41.328 10.413 -32.064 18.823 -20.651 18.815 c
--9.233 18.8 0.005 10.374 0 0 c
-f
-Q
-0.749 0.145 0.733 rg
-q 1 0 0 1 344.7393 -13.4258 cm
-0 0 m
-h
-f
-Q
-q 1 0 0 1 365.4141 -8.7441 cm
-0 0 m
--0.005 -10.372 -9.272 -18.773 -20.675 -18.765 c
--32.098 -18.762 -41.337 -10.345 -41.331 0.03 c
--41.317 10.415 -32.061 18.811 -20.649 18.808 c
--9.235 18.801 0.015 10.375 0 0 c
-f
-Q
-q 1 0 0 1 417.6318 -13.4922 cm
-0 0 m
-h
-f
-Q
-q 1 0 0 1 438.2959 -8.8018 cm
-0 0 m
--0.011 -10.387 -9.271 -18.783 -20.685 -18.769 c
--32.099 -18.762 -41.347 -10.347 -41.331 0.029 c
--41.325 10.405 -32.07 18.809 -20.656 18.804 c
--9.232 18.792 0.006 10.371 0 0 c
-f
-Q
-0.592 0.753 0.141 rg
-q 1 0 0 1 380.8906 203.7266 cm
-0 0 m
--46.693 0.042 -85.784 -29.726 -95.641 -69.599 c
--95.658 -88.415 l
-97.879 -88.574 l
-97.417 -39.622 53.785 -0.047 0 0 c
-f
-Q
-1 1 1 rg
-q 1 0 0 1 344.9043 157.8516 cm
-0 0 m
--0.015 -4.704 -3.83 -8.511 -8.53 -8.517 c
--13.234 -8.501 -17.053 -4.687 -17.051 0.023 c
--17.036 4.729 -13.217 8.537 -8.526 8.53 c
--3.814 8.528 -0.006 4.709 0 0 c
-f
-Q
-q 1 0 0 1 433.8613 156.833 cm
-0 0 m
--0.003 -4.703 -3.819 -8.521 -8.521 -8.516 c
--13.226 -8.501 -17.039 -4.694 -17.036 0.007 c
--17.032 4.718 -13.215 8.528 -8.514 8.521 c
--3.813 8.526 0.005 4.701 0 0 c
-f
-Q
-0.592 0.753 0.141 rg
-q 1 0 0 1 346.5068 186.8408 cm
-0 0 m
-1.099 -1.771 0.822 -3.932 -0.614 -4.839 c
--2.055 -5.733 -4.118 -5.02 -5.234 -3.251 c
--27.74 32.904 l
--28.848 34.675 -28.576 36.843 -27.126 37.743 c
--25.695 38.645 -23.623 37.935 -22.514 36.154 c
-h
-f
-Q
-q 1 0 0 1 444.0176 219.6338 cm
-0 0 m
-1.105 1.782 0.837 3.936 -0.601 4.847 c
--2.044 5.737 -4.112 5.042 -5.217 3.26 c
--27.797 -32.842 l
--28.902 -34.624 -28.64 -36.788 -27.193 -37.698 c
--25.76 -38.591 -23.695 -37.885 -22.577 -36.109 c
-h
-f
-Q
-q 1 0 0 1 477.2227 -42.2568 cm
-0 0 m
--0.007 -7.686 -5.353 -13.904 -11.958 -13.896 c
--181.146 -13.747 l
--187.742 -13.739 -193.078 -7.519 -193.083 0.166 c
--192.985 106.757 l
--192.974 114.43 -187.631 120.66 -181.023 120.645 c
--11.828 120.497 l
--5.233 120.498 0.106 114.274 0.099 106.593 c
-h
-f
-Q
-q 1 0 0 1 477.2949 32.7744 cm
-0 0 m
--193.085 0.174 l
--193.017 75.009 l
-0.066 74.838 l
-h
-f
-Q
- endstream endobj 810 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 804 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 798 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 792 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 786 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 780 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 774 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 768 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 747 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 761 0 obj <</OPM 1/BM/Normal/CA 1.0/OP false/SMask 758 0 R/ca 1.0/AIS true/op false/Type/ExtGState/SA true>> endobj 758 0 obj <</G 757 0 R/S/Luminosity/Type/Mask/BC 759 0 R>> endobj 757 0 obj <</Subtype/Form/Length 59/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Group 755 0 R/Resources<</XObject<</Im0 754 0 R>>/ProcSet[/PDF/ImageB]/ExtGState<</GS0 752 0 R>>>>/BBox[247.329 621.671 530.329 320.671]>>stream
-q
-/GS0 gs
-283 0 0 301 247.3291016 320.6708984 cm
-/Im0 Do
-Q
- endstream endobj 759 0 obj [0.0 0.0 0.0] endobj 755 0 obj <</I false/K false/CS 756 0 R/S/Transparency/Type/Group>> endobj 752 0 obj <</OPM 1/BM/Normal/CA 1.0/OP false/SMask/None/ca 1.0/AIS true/op false/Type/ExtGState/SA true>> endobj 754 0 obj <</Intent/RelativeColorimetric/Subtype/Image/Length 14305/Filter/FlateDecode/Name/X/BitsPerComponent 8/ColorSpace/DeviceGray/Width 283/DecodeParms<</Columns 283/Predictor 15/BitsPerComponent 4/Colors 1>>/Height 301/Type/XObject>>stream
-H‰ÜWizâÊU©4‹ ÓïWö•d5ÙM¶’UdIÌ(¡Y*©Þ¹%Ùàí×6ýx·ÿ´ù@Tö§ö«ðrÞõ8êaò§Ÿðç™w;{z”ü|þ*èœ?(4õæ'àù+ ÃΫ¢ `LgºŽdÓȆð¹êq>nþÀqmŠ®>©èœsɦÆ
-!ç†Ò –ÕÍ6J~Э¢í5LÇõ{=ß³¸V—EQÔÒpü^ß·u‘žŽ‡ Ê„‚&×e]•TH¡C<“„¿×q®3¯=Ó¹éxýáp4ðÎD™gØ€Ó
-NáH…ìozýí¡V9þènùð°¼ùD¥‚Þb-s,.«4<æÛæ" ÛÝ>L…‡ƒ½5Už¦)dªQIRiPS+ú#ǹæüø8L7Þd¾ú´^ÍGP`MY5ŒÉæ$²8 Â8o¸ ZÙ¬NOûÍf¤BW"¤7E¢IHCZÒuMÖuçõòù럀º5tœþdñðÛ§Õ|ܳ¹FÛhZW­ê"M¢8-Ãv=`!²Ó~»Ý™
-£´ ’Y ›tQèÅ·ü²ù&:Xt¼ÝÝ?¯†žeè_¼Y>?AÑ ÿ‰gu+B…@¦v )1ÜÑæ¤5wûýÀÉ¢ÃáÀë5ÝDB̬*¶€ Õòù¹ò…~Å|¦éÐM~µX=¬îgCÏþ
-8ÓÒLÙ™¢_Ó‰P£¦m‘“Ÿ[¸WÖ@ƒú}Z¥p·Ý" † d“yÊVˆBJ…Yµæ…~Å|õÆ„ 7m·?œÍ—«å|úCpÎq·[¥'‚v™œk"U3-$ã;\$ÁvóˆL]ëBJ„²$ŠäD½•ù†F^4Žkãôµ+ÃÈ 0šÎ÷‹»ñÀý­>y~à“5tOR+Q¦Qž´Û£6Fà<>Ò*qÇÇ !Hxx:µÔ[áj„Ò eöí&]Ý꿼3#5¶ÝÞ`8™ÞÍïf“!‚s9"ÔjP•§qœ ™(_"tî6ÛÝ)o€V mìtÀnÅìyÀ :&E…:V!(ªÂ¡âÕÕiöÅ¥qÊëG“él:›Œ‡=Ù…½œÏDK
-QǺÆÁ‰› ™
-A(ÍŠ¦ B†¬’
-B¹òä#,Tÿ2³'¬w*ÌIÇì2¿úp8?iÐÕì¹ í…j˜}x
-¶› 4p4M­e—»œ/×>TI¤ „8pØNàäI·x’y
-ÕyåøñI·>Ž­$6§Ñ6¬Á ¤So*¥ß3 z2{.ÀMÛsÁ.8„™ À½d!;Óæ,œÝ9ƒ})"2¶ó©’0¯—kîìüdöô“e?òÖMò½€ÓZ†e÷m(ògÁ©<è«ÙgÜ©’»}†:v>ç8ïNQDÜÙžÕ1Ö8êªTM°ZÞfw +¼øPoBõ%Né\s³O³Ç-ýÀFàkH]zÛ0-Ë4ÚÕ/I%_~h\ô˜a’^ ¡¾"u­j|oín¬q¨—ä dO°ZC©eÑ1ØÂìÏ!à°@BÇJn›DCo8ŸÕlwŒžÙëbq>E_|ì
-”›Ø!=íœÕ¹ñ’ ¢ˆ”A¡I¢CŠ›åá W©z‡û§Õ·ÌnSÃMÕ>MŽ_Ÿê‘yk4N$ÊEAë]‰/ûÝv»CS•ëˆÐ²œ}g 8AÈä!C½=@¢-ã´4\•\oõlî_”ÿHoÚà/†s¥ódÂäÊÄ "G àðìf’ð´Ç™¡AjrPMÎHB˵‡]UU‘ø,:ƒŸïØ·¼f”š‚d­cÆÜ¿f[SÀ†ûz6Otu"WhÐI™q$B\¢3 ÓjM¦68ç¬í1æå:Ìž'ûÚ¸®» ˜½—¤C’£w­ÑxÌýÇl×eÒ›oÀæçrbÆ~ÿ$B¸³$‚Ù‡1Ôf_ã9¤Bßs7;Dh%‡}wµZ9Ûý)*­:€ƒVeþ6rÿm5Ȩ¾›×è°?¬ppyáˆbªV<ó¦
-™ýÎ÷a
-± ³JÃÃÖYÌç+×?†¥ïŠàh€ó÷ñÐä&д/ã§÷"g"”»-£À—§Üµ­¨"H²"S¨>lÖóét¾Þè®JNÀ ŠÖ±‡Ø«Íyhsß΋tþ_„*ì̲JnöìÎ.gw\j Õ€³œMf«Íþ\Nµ&ims8íŽÎík_Ž_z/Òyþr³g_ÊÔ
-nŠ{žŽïžÊD IöVóɪ`uÊÀÁYu¬áh4@sÅø/Œó¡ï:XËÞ_/&“ Vçx)~W$Èr£möGãÝÑUQà~ªU÷N'_Ÿ…dä@vW…? V^oý!îÊhÕ%¡úsç¼{:iá®XƒXRÔ)£ÈBMÕºù]uŠÀÿ çÎéduNÁæ
-'('¿«Áx4´»(†sÏt2–t¢Ón³œÑY•ݺ«Vo0l£ÉJç_ç^ñqÀ&ÅU]Ž;o9›Næëm9ÍÉáPäQp¤—àÜ+b“€ÍiAžÏæKwWÊ­*U^±9öh<|usî”cEçÓ>Ø8ëÅbålö§âÕlª‚¨4ІÃÕÕÔ—4§ø8Ÿö
-“›Ëù¸ßm=g½rœMp¼NÈ9©®wL{Øï£?ȵWàÜ!æS—Óaço<×u\ÏßÏQá«B>j²ª· Ó¶m!ð…œSbœÏ|ïCÙ8„Ül‰Œëmý=Ø_ˆqM®k­nÏ´Í^·I‹ó¢äçSß»ãÐQ¾ç®Ök°ÙŽ—(.®8Užö¦ 6¦itÐ;Å×§È8ŸûÞ‡'<[g¹\®Ü8MšV
-þIÕÚ†iY¦Ñn6©V}}qÞç³ßÛãPú£€³^ÌKZœßTqÅ©Éô¦o[f‡Øª¥Æùô÷æ8W8îj€£Ââ$…ÙP­Q«Ìþ``õZš*‘à¼Éæ®èÐY]N´9³ùbí!þEi‰p\å¥zÓ°†Ã¡e@Œ‘ÿª•wàÜhÎiÍYÌpWÛ} '8‚HÅa8Øpª"‹óÎ8_ðއŜ\tfX<
-l¨"Ï¿kWoóUïÅq2²«˜‰Îr:-\¿Ôæ@‘™"²:½®^GB.tW÷@çÊærÜoÜålNšsŒŠÃáHtD«cŽÕ…aÕø‚p¾?òªˆØøgµ\¬Ÿ‚Nq8Õ*/J¸+¦:&åÀâp¾;b_·`·ñœõzMå*Œ“â‹ÉUkuP=M´+RäÂp¾9J€ÈÇ»íÆu]ÇÝlƒÃåÌ—k’ªZ…EDEä©Õz=ËÍL¤^å Š‚ïÎÜzêÖêƒ]‚RžS!;÷™+×*ïM‹f9^¥¡¬(#ÓUÉ]~µœG?ïÊME´8ŽÂ0Œæñ"[»}iˆjÌv{bØÀϰ«ŒN¹mu¥œÇ?oËA‹³Y-Pnü0JY¾ÙíK+à }Iɲ$õE¡Ë1·LÕÇržàySÉUYy®ãó”°9¥á´èzEU†’(ðË ßçyé œb™®™3][œ©ò«ª…Á
-üŸR,t; Ý.<¿(ç)ž×rœ,8ª¢ÅªØï˳AwÌò}E7MC¢ÜÐ-Œ·ÂyV: 98V¡g[¶w¶8e7UƒÀéôª9™˜êPäØsÛÜÌæY震Ãf½ˆ|Dz ^æ8Vå_‚p$Í|y1¡s8æÿeó´tÀçYºØ:QºÚ —~Àá%u<y™hò/8?*çYžs9 :ûÍ:|Û² unŠ(È,?PÌÉËXõo´WËyš‡”ƒFg›/ãÀ™AëÌùö8Øœ¾¬'C‘ U¡ÿ¨œçy ø9À"Ç¡cY–- XÝ|Ž ©ÆdŒ¢Óe~Ò:OG爚“%gaç¤ùmpš4Ûí4sb£´ÎîøÃ랉ΩA ¬+\æŽÌ—7Œu‰½¡b˜c²Ì±u~PÐ3ѽ¡Š°ÉÒ9„+×’lSZ!%PÍ&Ìß—5€£Ë}œÎOà<Ž«ešDQàQ²É9”fÓl5[m˜+aˆ&Y‡¹b韈Nã‰è`tØæÔIEaÍÓåjSÖ!c×´Ûmš¦Y®×©†¡ÝγÐ95`‰YJý'
-Â0š'‹l]ì0w–ø2ôM«Í0,>dÏ‘ŠÑ“ÿ9œ'¡CbÕz1©?}?
-çêJ9׿Œ$ÕMu¢SOëÔFçÔ8¶`ÎÔòç°Í¯ÁùŠN³Ùƒ,Ÿwù
-ÒU=ÛêR@…t`ªHv\Ïõ¡o€Í·Óø@ÓCØŒ4MS€ ÏÖås^+¨ŽN‰ŽãQºÊ·ûã·ÓxG‡ìqûFÓ ›]“C~SCetN¾Œ}Dzœ`Ž‚s86~wÚß—Åa‰4tM‘DžeÚÍz§Q!3œ¹oÏfŽ?_®·‡ß Õ¹œ×ÿ€ƒÔMÓÐ@Œ; öMÝp*£ƒš“g$‡E¾ý^_˹üÛlÒHæxb`ê„èð
-0VÐ9êøåÅÔ†B‡©Ñ,§
-:ç]{öt:ó¢e¾+#ÈçrD;=МÉËX“Asjö8ïʹ?pÈÇŠŽ=ûËr!u~¬>–C< ËFÆd2Ñ•>϶›uºãåÜ™Îéœ;7YBàÀº* 8 AîöQtƦ"Õœ«>•sW:ÀæxAÎÁ";ÖÌÆ]~Cç€7‰ j°ËMU:ôãD§q_:ÈæpØíŠõ2 <òCœÝ 9Ð8MЦ™®(©H…sO:8Rûí¦Xg‹8ô=³Õ¦ô¶"‹¼E‰^*†aê
-îòǹÂfSäY–¦ó( Â(ÉÊ:dRÍRÿ²¢Úÿ¸/ÏóÆÕ#
-L`‘pûpnÀ…¸÷á
-Ü…»‹È90€Ñ3 6Ü»+éƒD‹à~¿%pž÷9sæE䦣þáÜŒñýv]dY’Äð’¬ÄÞI~ɑ̈́¡þ"H²ªÈ"lÝ¿§!_Ǻ 8âÇýn¥qÅI’fE¹Ýš§‡l8ú›¬H’È1SrÎýNù×¹nA[Uµ.â(ðÃ0Éòr³­ 1¼â°RŠBýC–™@@¾÷VՃ݀nœÈw=à€löÇc6Tw0š±’¢i*õ/žeÆ£:ÎýáÜ‚NÝà†»Žãq¾Ùí›è·
-„#* }¡‰Ôfº-lnAç¹T®m9A”¯«CÝàVõè HªÈRä¿¶°¹ð\«àØ^”®ÑŒ;Mà@«‚ô·¼VNjƒ‡ª%l>NçÒ9ªMyŽeC6.šDœÎÎŒWŒåÒ8ãul›Ðʹ-“Щ¥ƒá¸1®†£œa:·ˆÍ‡éÔ{…Ò±WÖª]ƒZuõœ)'ëæc!±“!lÕ kß ÞÇÆÁx؉ïX+Ë‹sØ«&p¨þpÌJš¹42Å,ç7¢syN:»ZYn˜möÇFpzƒ1#¨úΕÀ@
-–*EÀ^¯õÓŸ=.3îÔ*DZ=HÇ[òSÙqо4 Uœë€óšfã|Æ#où~S$°XЫ¢|Ý@:×µå, Md't¿ûK6LêÃn“G¾kÙ®Ÿ»}“˜3œ²’f˜Ð8¹)”ªî¯á<,,W‘A:öÊöÂ|Çœð7¨ÞpÌŠn˜ 0Ü«Ÿ§á8ŸóHǹÔ9p“Ežm­œ -+òÚIu#8WšaèšÄ¢t^Ø«¥åêr:VÛ<ö•eq¹;@D&û0kÐ1Œ…Â3ãAÿE8H§fÊÙæ \sËAÓ94èýáxÆËttL:tï%Ó!çßÛã
-ж*§N8°Sdl
-§ÕtðT›2‹ßq}sšÀŽöÊX¨";¡‰ºÃ+ãÜÿý0t³)²z§ïGI±Ë9“~=g pT]וwÂi/Îalâ ðý0Jó ´‡&–3 §s^V M~^«ÆpZK®øa»N£Àóü N‹õî
-2Íõ–Ã^9(ò½zVŽf •ó1átZHç|Þïà^9Ö“íFYƒÖyõQÕMS¯=§÷îSõý›­¢s¡NpÌ1é¬V+'L×䦃×j4åå…aèª4Çøaé´Šxµ‡â™E®õdÙçØ YAÎañ\é°W·‘N‹è
-2òz>þòe¼Ø„©
-œ"‹öÛÕr¹\mܤ‘oG:{v ¥´ÙŸxe>ˆ¤@b²$+$Õözý~Ç;‚åÌôûÃAvV$QˆÞ¢¬7<ÂÄo媿žT_ÞÍ®Y¤8ð©Õb>[¬6„ üµþáÓœ‹ŽX’ôÌYU Æ
-S%†&\½í²ð*`“¥Q°]-fSxù¯5G¼æ-þ|¿“Äx½ŽÃ+ˆPÅ™f‚fžkÀëcx}ÁtâÙ¨/àÂl±ÿȺíy>DHa5þSUI$dMcÒõIVl’(ØmÖ‹Å9ú•[]{ÌïÖ©q4™ïhõè ÆíÀë5´ x}V1Ý“ãÁÏ’(JKöo³ ÷[†*H±\V ÃÐeõÚ$$8•Åáa·Ù¬–«õfÁy=ç|û–?³ØÉ—¥ZX=DH7©ZIðú U‹é64§ß…}q;SØ¿|ˆP׳!Bi’dˆÝºåX–®‘Î_„08%°Ùš Ù„€ÿ8F‚¤ã³htjgM^_rY³Zp+´1žƒgY¥:ìŸHBèª*Ïâ(Š ®Yn«åRI­…D¨ Wââgæ Ñ:ÍjñöË4¹m+ÂxÀÃB€
-hsVª}Ñ¿ú­A5;‰ãt­è–í0Ž)¼~…àTÙÛ&TÕt<¼ dz‰³ãâ¼õÏ}á«ß™Ø˜Å69L[üƒlýGŸXâ\A™'QRüÛ®G8¦Áƒ2.RêZõïÁXiȳˆs7š ãì#ÎQÕ©,ý§p ë «é¶\Gü¥fhlÂâ”z#½âµj6¡pL£&´‚é(B:¡MÖ¿‚1Žò€îj0¸C;ŽwÉñÚ˜Ÿüµwýت´TÀjàh,]ü‰;£´ÐlŠk ¨Ei¯"ý{ÝŽ CYJ3Eš¶Í¾Uf}U¯^ªÃ%0ZÎ›Á\õjÌÏþÞ;ì àÐ Ó´
-ácJÌÇ£»áÃl‰Jp8ç§Î +£‡˜ƒ ¦­›6yOI
-ÿÿÿ
-H‰ìÓË’£0Qûÿz¦{¦y¸rA
-lè
-ÒDe¤‘fNNLÌ?
-““S“†RS“†R“†
-ʤ‰ÊÔ£ ËH#Í”4œ4˜4˜4˜4˜0˜2”2˜2˜2”£Á”¡ ’)I“©H”‘FšEÒ`Ò`Ò`Ò`Qš‚6Ò`ašz6ÒPÊ`ÒPÊPqi¤ùŸ2˜4œ4˜4œ4˜4˜4˜4X˜¦ž4˜4˜4˜4˜2˜4”2˜4”2˜4TX¦M\Fe~’ó‡â¤Á¤Á¤Á”Á”¡ ¦ ¦ åh0i(e¨¨L=š°Œ4Òü—‘Fš)i0i0i0i0e0e0e(e0i0e(Gƒ)C9*(#4‹¤Á¤á¤Á¤Á¤Á¤Á¤á¤Á”¡”Á¤Á”Á¤¡”Á¤¡"25iB2%ib2i‚2ÒH³HLLLLLJLLJL*(SFLLLNLL,HSÑFL,JSÏ&,#6SÒPd¤‘æ_ÊP[d¤‘æ»M2µh\ ' & & & & & & ¶‰¦–4Ô6™R6Ò`[iêØl–)c³C¦ŠÍ.šWœ!­vʬpÆÒ~™ÕH3šÍ‘4£ákóÍ3
-Óá4K¤¾;‘¦w›3if.N¦yÃÔMÒôfs%ͤӅÓÅ2¿•î["ÍÝm2iîm“*3ë,>ïR²ËKÙ˲-~• 2—-ñ®ÅeÒpÒpÒpÒ´šO•†“†“†“¦‘4­æÛ¥á¤áÖÏ‘fÝê-ÊpÒpÒ´šž§ § 'M#eZÍ/V†S†¦Ñ
-]¦¤°{ôG€
-8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0
-b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup`
-E1r!/,*0[*9.aFIR2&b-C#s<Xl5FH@[<=!#6V)uDBXnIr.F>oRZ7Dl%MLY\.?d>Mn
-6%Q2oYfNRF$$+ON<+]RUJmC0I<jlL.oXisZ;SYU[/7#<&37rclQKqeJe#,UF7Rgb1
-VNWFKf>nDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j<etJICj7e7nPMb=O6S7UOH<
-PO7r\I.Hu&e0d&E<.')fERr/l+*W,)q^D*ai5<uuLX.7g/>$XKrcYp0n+Xl_nU*O(
-l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 719 0 obj <</Private 720 0 R/LastModified(D:20080601013506-07'00')>> endobj 720 0 obj <</RoundtripVersion 13/CreatorVersion 13/ContainerVersion 11/AIMetaData 721 0 R/AIPrivateData1 722 0 R/AIPrivateData2 723 0 R/AIPrivateData3 724 0 R/AIPrivateData4 725 0 R/AIPrivateData5 726 0 R/NumBlock 5/RoundtripStreamType 1>> endobj 721 0 obj <</Length 894>>stream
-%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 13.0 %%AI8_CreatorVersion: 13.0.0 %%For: (Jason von Nieda) () %%Title: (Android.ai) %%CreationDate: 6/1/08 1:35 AM %%BoundingBox: -261 -153 1275 829 %%HiResBoundingBox: -260.6709 -152.7559 1275 829 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 9.0 %AI12_BuildNumber: 406 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Registration]) %AI3_TemplateBox: 300.5 399.5 300.5 399.5 %AI3_TileBox: 12 44 588 778 %AI3_DocumentPreview: None %AI5_ArtSize: 600 800 %AI5_RulerUnits: 2 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 2 %AI9_OpenToView: -220.3833 938.3823 0.6667 1543 1054 18 1 0 90 75 0 0 1 1 1 0 1 %AI5_OpenViewLayers: 77 %%PageOrigin:0 0 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %AI9_Flatten: 1 %AI12_CMSettings: 00.MO %%EndComments endstream endobj 722 0 obj <</Length 8538>>stream
-%%BoundingBox: -261 -153 1275 829 %%HiResBoundingBox: -260.6709 -152.7559 1275 829 %AI7_Thumbnail: 128 84 8 %%BeginData: 8392 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FD57FFCFFD38FFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFF %CFFFFFFFCFFFFFFFCFFFFFFFCFFD1FFFA6FD05FFA7CFFD78FFAD81A68181 %82ADFD37FFAEFFFFFFAEFFFFFFAEFFFFFFAEFFFFFFAEFFFFFFAEFFFFFFAE %FFCFFD05FFAEFFFFFFAEFFA8A8A8FFFD11A8FD06FFAE7A8056817A8056A7 %FD51FFA1FD1BFFA9FFFFFFA8FD04FFCF80A6A6FD0481AD80ADFD35FFCFFF %FFFFCFFFFFFFCFFFA8FD09FFCFFD05FFA8A87DFFFFFFCFFD05FFA8FFA8FF %A8FFA8FFA8FFA8FFA8FFA8FFA8CBA8FFA8A8FD04FF818081A656817A8182 %8181FD40FFA8FD0DFFA8FFA8A8FD0CFFA8FFA9FFA8FFA8FFA8FFA8FFA8FF %A8FFA8A9A8FD04FF8180FD0981ADFD36FFAEFFFFFFAEFFCFFFCAFFA8A8CF %FFFFFFAEFFFFFFA8A8A8FFA8A87DFFCFFFFFFFAEFFFFFFA8FFA8CBA8FFA8 %A9A8CBA8A8A8A9FD06A87EA9FFAEA7FF82A682A682A682A682A682CFA7AD %FD3BFFCAFFFFFFA8FD07FFA8A8FFFFCBFFA8A8FD09FFA9A9FFA8FFA8FFA8 %FFA8FFA8FFA8CBA8FFA8A9A8A8A8FF8180A6A681A5818181A5818181A6A6 %817ACFFD33FFCFFFFFFFCFFFFFFFA8FFCBFFA8FFCAFFFFFFA2A8A8FFA8FF %A8A8A8FFCFFFFFFFCFFFFFFFA2FFA8A8A8A9A8A8A8A9FD0AA87EFFFF8156 %A681817A817A817A817A817BA67A81A7FD11FFA8FD28FFCAFFCAFFFFFF7D %A8A8A87DFFFFFFA8FFCAFFA2A9FD09FFA8A8FFA8A9A8A9A8A8A8A9A8A8A8 %A9FD07A8FF818182A581818081818180818181828180CFFD0CFFA8FFA8CF %A8AFA8FD1EFFAEFFFFFFAEFFFFFFA8FFA8FFA8FF7DFD05A87DFFA8CBA8CB %A8A8A8FFFFFFAEFFFFFFCFFF7EFD05A8A2A8A8A87EA8A2A87EA87EA87DA8 %7DA8CF8156827B817A8156817A8156817A827A81A7FD09FF7D7D27A8A8FF %CFFFA8AEFD27FFA8FFA8FFA8CACBFFFFFFCBCBA8FFA8FFA8CB7EA9FD09FF %A8A8A9A8A8A8A9FD0AA8A2FD04A8FF818182A6FD0A81828181CFFD08FFA8 %5227527DFFFFFFCFFFA8FD1EFFCFFFFFFFCFFFFFFFCFFFA8CB7DA8A8CAA8 %FFA8CBFD05A8A9A8A2A8FFFFFFCFFD05FF7DA87EA8A2A87EA87EA87EA87E %A87DA87EA87DA87DA8FF817AA67B817A817A817A817A8181A67A81A7FD09 %FF7DA8A8A87CA8A8CFCFCFFD27FFA8FFA8A8A8FFA8FFA8FFA8CBA8CBA8CB %A8A97EA8FD09FFA8A8A8A2A8A8A87EA8A2A87EA87EA87EA87EA87DA8A8FF %8080A6817A818181808181817A81A68156CFFD0CFF5227527DA7CFADFD20 %FFAEFFFFFFAEFFCFA87DFD0FA87E7E7EFFAEFFFFFFAEFFFFFF7DA87EA87D %A87DA87DA87DA27DA87D7E7DA87D7E7DA8FFA782AE7B8156817A8156817A %8156AE82A6A8FD09FFA8FFA8A7A7CFA7CFCECEA7FD26FFFD05A8CBA8CBA8 %CBA8A9A8CBA8A8A8A97DA8FD09FFA8A8A87EA87EA87EA87EA87EA87EA87D %A87EA87DA8A8FFFFFFCF817A8181817A8181817A81AEFD0DFFCFFFFFCFCF %CFA8CFA8FD20FFCFFFFFFFCFFFFFFFA8A87DA87DA87DA87DA87EA87EA8A2 %7D7D7E7EFFCFFFFFFFCFFFFFFF7D7E7D7E7D7E7D7E7D7E7D7D7D7E7D7D7D %7E7D7D7DFD05FFA7A67B8181A681817BA682FD0DFFA8A8A8CFA8CFA8FD30 %FFA8FFA8A87DA87D7E7DA87E7D53A8FD0AFFA8FFA8A9A8FFA8A9A8FFA8A8 %A8FFA8A8A8FFA8FD08FFA656ACFFAD5681FD37FFAEFFFFFFAEFFFFFFAEFF %FFFFCFFD05FFCFFFFD04A87D7E7D7DA8FD05FF7DA8FD1EFF818081FFA780 %7AFD58FFA87D5252A8FD0BFFA8FFA8FD0EFFA656A6FFAD5681FD2BFF7DA8 %FD0CFFA87DA8FFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFD09FFA8A87DA8A8 %7D52A8A8FD07FFFD06A87DA8A8FD0BFFA781A7FFA88182FD2BFF7D522752 %FD0BFF52FFA8FD17FFA8A8FD06FFA8827DA8A8FFA8A87DFD04A8FFFFFFA8 %FD3CFFA8FFFFFF7DFFAEADA7AEA7ADA8FFFFFF7D52A8A8FD1EFFAEA78281 %7B7B7BA8A8FFFFFF527DA8FD13FFCFFFFFFFA8FD2DFFCF81A681A681CFFD %04FF52FFA8FD17FFFD05A8FFA8A682CFA6AC82ACADFFFFFFA8277DA8A8A8 %FD09FFA87DA8A78383CFAEFFFF5252FD2DFFAE81A781A682A781CFFFFFA8 %52A8A8FD16FFA8A8A8FFFFAEA7A7577C57827BA68382A7A8A8A852FFA8FF %A8FD09FF7D525252045181A7FFFF7D7DFD2DFF82A6A6A681A6A6A682FFFF %FF7DFFA8FD1BFF82ACA7AD82A67C827B8257A7FFFF7D7DA8A8FD0CFFA8A6 %82827BAD82ADFF5252FD2AFFCFFFA8A782A782A782A682A6A8FFA852A8FD %17FFFD04A87D7B7C827BA682A682ADA6A6A7FFA85252A87DA8A8FD0BFF82 %A682A682A682FF52A8FD2AFFCF81ADA6ADA6ADA6ADA6ACA6ADA6A752FFA8 %FD15FFA8FD04FFCF81A67B827B827BA681827CA782FF52FFA8FFA8FD0AFF %ADA7AD82A682AC82ADA7587DFD2AFFA78182A681A6818281A681A682A683 %7DFFA8FD1AFFFD04A681827B827B827B8282ACA752FFA8FD0CFF81A682A6 %81A681A682A6267DFD2AFFCF81AD82A682A682A682A682AD82A852FFA8FD %17FFA8FFA88282AD82A682AC82A682ACA6A67B7D52A87DFD0CFFA6A6A681 %A682A681AC82517DFD28FFA8FFA78182A6818281A6818281A682A67D52FF %A8FD14FFA8A8A8FFA8FF7C827C827B8281A681827B827BA6527DA8A8A8FD %0BFF81A7828281A6818282A62D7DFD2AFFCF81ADA6A682AC82A682ACA6AD %81CF7DFFA8FD1BFFCFAC81827B827B827BA6A6ACAD7D7DFFA8FD0CFFADA7 %A682AC82A682ADA7517DFD2AFFA78182A681A681A681A681A68282837DFF %A8FD16FFA8FFA8FFFFFF82A682A681A681A682A77BA752A87DFD0FFF8182 %81A6828282FF277DFD2BFFAECF81A682A681A682A682FFCFA827FFA8FD14 %FFA8A8FFA8FFA8FFA8FFA7A6A6AD82A68182A7A78352FFA8A8FD0FFFA6A6 %A7A6A7FFFF7EA8FD2DFFA681A682A681A682A7FFFFA852A8A8FD14FFA8FD %05FFA8FFA88257A8A77B7BA7A7FFFFA87DFFA8FD10FFA782FF7BAEFFFF27 %7DFD2EFFCF81ADFFAD82FD05FF7DFFA8FD1DFF82A6FFAE81CFFD04FF52A8 %A8FD11FFAECFFFCECFFFFFA8A8FD2EFFA8A6A6FF82A6AEFFFFFFA8A7A8A8 %FD14FFA8A8A8FFA8FFA8FFFFADA7FFA781A7FFA8A8A8A7A8A87DFD47FFCF %81ADFFA781FD05FFA7FFA8FD13FFA8FFFFFFA8FFA8FFA8FFA9FFFFCFA7CF %A8FFFFFFA1FFA8FFA8FD40FFA8FD06FFCFA8FFAECFFD04FFA8A8FFA8FD18 %FFFD09A8FD05FFFD04A8FD0CFFA7FFFFFFA8FD44FFA8FD1DFFA8FFA8FD07 %FFCAFFA8FD0BFFCFA682AC82A6AEFD32FFFD06A87DFD09A87DA8FD20FFA8 %FFA8A8A8FFA8FFA8FD0CFFCF7A817B817AADFD31FFA8FFA8FFA8FFFFFFA8 %FFFFFFA8FFFFFFA8FD27FFA8FFA8A8A8FD0BFFAE8180817A81A7FD79FFCF %7B8181817BAEFDDAFF7DFFFFA8A8FFFFA87DFFA87DA8FD72FFA827A87D27 %52A8FF527DFF7D277DFD0CFFA8FFA8FD64FF52A827FF527DFF7D52A85227 %52FD0BFFA852272727A8FD62FF52A852FF7D7DFF7DF8A87D5252A8FD0CFF %A87D7D7DFD62FF27A87D2727FFFF7D277D525227FD0BFFA87D527D52A8FD %65FF7DFFFFFFA8FFA8A87DFD0DFF7D7D7DA8FD69FFA8FD09FFA8FD07FFA8 %A87D7D7DFD69FFCFAEFD07FFAECFFD08FF52F852277DFD69FFADA8CFA7AD %A7CFAEADCFFD07FFA852525227FD6AFFA7A682ADA6A782ADA7FD09FF52FF %7DA8FD68FFCF82A682A682A782A682A682CFFD06FFA852A85227A8FD67FF %A6ADA7ADA6ADA6ADA6ADA7ADA6FD06FFA827527D7DA8FD66FFA7A682FFA7 %A682A782A6A7FF82A6A7FD06FFA87DFFA8FD66FFA8ADA6ADA6ADA6ADA6AD %A6ADA6ADA6A7AEFD05FFA8A8A8527DFD65FFAE82A682A682A682A682A682 %A682A682AEFD04FFA8525252F8A8FD65FFAEADA7ADA7ADA7ADA7ADA7ADA7 %ADA7ADA7FD08FFA8A8FD61FFCF82ADCFCFA7CFA7AEA7CFA7AEA7CFA7AEA7 %CFA7CFA8ADA7FD68FFA7A682CFA7A682ADA6A782ADA6A782ADA6A782ADA7 %AD82ACA7FFFF7D7DFD62FFAEA782A6A7AE82A682A782A682A782A682A782 %A682ADA6A682ADFF52275252FD62FFA7ADA6CFADADA6ADA6ADA6ADA6ADA6 %ADA6ADA6ADA7ADA6ADADA827FFFF527DFD61FFAD82A6A7AD82A782A782A7 %82A782A782A782A782ADA7A682CFA852FFFF52A8FD61FFA7ADA6ADA7ADA6 %ADA6ADA6ADA6ADA6ADA6ADA6A7A7ADA6A7A7FF7DA8A8A8FD62FFA782A6A7 %AD82A782A682A782A682A782A682A782ADA6A782AD7D27275227A8FD61FF %A7ADA6CFA7ADA6ADA6ADA6ADA6ADA6ADA6ADA6ADA7CEA6ADADA852FD65FF %A782A7A7AE82A782A782A782A782A782A782A782ADA7A782ADA852A8FD64 %FFA7AD82CFA7A7A6ADA6ADA6ADA6ADA6ADA6ADA6ADA7AD82ADA7FF7D2752 %A8FD62FFAD82A6A7AE82A682A782A682A782A682A782A682AEA7A682ADFF %A8272727FD62FFCFADA7FFADADA6ADA6ADA6ADA6ADA6ADA6ADA6ADADFFA7 %ADFFFF2752A8FD67FFAE82A782A782A782A782A782A782A782AEFD04FFA8 %A8FD69FFA7ACA6A7A6ADA6A782ADA6ADA6ADA6A6A7FD05FF52A85252FD67 %FFA7ADA7A682A7A7ADA7A782A6A6ADA7FD05FF7D527D5227A8FD68FFCFA6 %ADA6FFFFFFA6ADA6FD09FF5252A8A8FD69FFA8A682A7AEFFA8A782A6A8FD %08FF52A87D52FD69FFCFA6AD82FFFFFF82ADA6CFFD07FFA827A852527DFD %68FFA7A682A6A8FFA8A682A6A8FD07FFA85227A87DFD6AFFA6ACA6FFFFFF %A6ADA6FD77FFCFA7CFFFFFFFCFA7CFFDFCFFFD49FFFF %%EndData endstream endobj 723 0 obj <</Length 65536>>stream
-%AI12_CompressedDataxœì}‰b·óð÷ûæOÃ{oír5>)HJÂÑR޽I Ž|´å÷ôߌ4£•5Gb§ËjÏJ³i4·ÖkW¶wÖËíþ~²î킵¶V$ÍQp· ¡…ÇÝîx8 èÆ‹›ZA£òãh¾JÃN¿wWÞ’7ØûÆ“æ°ß+ü Ÿw’vófáÆM¸·Ûu¸[îµýN»ØìÜäg’Zs7Ã’S²£‚s×
-ågp»Ò÷ÚÞa¥ÿïݺ:…u'ð
-Ž+‚BäÆÐâ·Î‹d8ÝÌ.†Âޱ­[A›jýÖø8é¶ýV2VûÝþ`x·PýÒìž5áN³ðGÒíöÿ)TºÍÖ'£K£ßAÓò Óì>Û…· •~ÿÓq³·Õmt“y°õJ¿Û–7ãÑxÐ\–´;ãc yöpµa(ë/’Ãq·90žö<IÚIû\žY~ì5:ÝÖï¸9*ĸ˜åÇŽ»WwºíçããýÖ·C{{rÎ^a²`Þð3‚ÅÞãc€ì$£¬ âÅ£Š9Ï
-þØd×ǺÑcÕhK5Ú2ð1Ý[ªÅKÕâ¥‰æ¥ºÕÆ•;%£·Zˆãfk€üò^6k¶ä†P[Zíh«t4î6ããns<‚}*áS©Õ„~Ön]ŠÐàÉÞîGª/¼=)¦ê½Vm‹»…=RÂZ¿-1¨Ä·”rØýS!
-»ý~Woò–&%Û/Ç3¶e‡ÞVOÍô쓨Áô“ÀŠ^º§@ëÓŸ
-îMkd«[¨€ª¶î[¶úãÀåÚ\¾ÀڮȎá*Û¸ªvÍ®Û hè8.\žã;¨ŸÐ >b§ìTàªZNÍ©ÃÕpmh庞뻺ÂÜØ-ÃUq«nÍ­» xšã¹žçù^à…ž
-3’Ä"a’Šfw‚æ1³3²„g¢EÌe‰Ó™B±…b faIþ˜ä;òšd…ôg©:—«.Kòú4¿§?¡µFd}˜jCbq×±€»g#_#O#G#7+ÍÁ2!û6€u‘qCà dØ:<Û6 AËÀ›u… üZÀ†•°rݬe xË~Š€ƒjÀ7°I ŒÑ
-ËS†EŠ@f„ =|#.ÈÛSSaS†Ý¼Aù \L6¨ª:Hª*(®2È­äWrÌÆp=l¯R®ìR¦‰½È!ù ]à)Ûm
-ò±Êš@ò·,ítQ`FSË+šñ¯/÷rº”x•ÉLUkJ¡¼©Iq
-Ö®ŒšØEù>½uŠæ²ˆ$`¾îšÖ^“ú+Õ`¤Ã¬©ÁË¡K¡¤DÅ$#%$%%%&%‡ JIâu!¢,MSÆ«3I“§T$*­ˆÔëdiJdXpbz‘âʤêpcßqPà» ÷]>€¿0Y¡î¼`Y
-l4
- Ærw ¹Û"ôåNtå¾´e¨°!wkM «2§_–aÃX†#¹ÙC+ e 1 9 ãŠHJØ|¤iSw±®ÕuÅpI9k×Ñ'­üUlÉ%O}üPæ‹|íQšz¹¡u3kgÖϬ¡',RÓìi²¯)Õµö8™UªÚïTÊÙ†½ÏP±U•²—¼P7õDµZ¯“?ª=RFЊ>¢h‚PÊ/dÙ…â:öís%qØú‘¼X× vN¼s–þXĤ|EúW˜^Ò03,‰€¢£EG[Ò4@·­ÀŽ£Â<7yÑŽsì/sÄ9ÝŒÐ÷Ï´"¦‹<O/uÚìôYTEÖ„&Æ,ìâ (u²æV¯œ^ê¤,„úé¥NÖYÕ*S¥NfmW&˜¥N5˨SqgŠÒš„²¬I˜-Tq§ U¬™J•´þÀ,O©sù“Q
-.¬{+]‡ÁzÀ€1Hèˆ=L£r¥zå
-~DzYô¡NQŒº1PÕ1 3®QÖ‰ µ[µU‹†A$|$š°Ê"Te\••7ªÊXLUs1X–4 ì“À“á%¡jÁ*p`/`µq,MÉ:‘h@°“bi0¢±ˆf"˜ˆ쿘ŒBuäEv ¥‘_–îºu é̹ò K Ï®Dtj¥B‡Uä1K†k¼AßÉ׌Ãì’2Ê4ƒÀ«Ê+µUÒÍ¢¢±e£ÞMU»¹S¥nsŠÝ¾×@œûgÙšÙéIÿk~aüdšf:Ŭ6–ãè¸:GÔÉ=SÙf*OŠ§ê³ØgoÍfÍÒN‡Å9µheëVÑíúD®G1¢Œ¥“>ʹF懼*e€Òj5R5{J#Mê¤yZiJ/M¨%C1Y§k¦³uÓ<ÕdiÝôMÚiV9YßY`г¦uÁ¬N˜¾¢S¯8½,óË„*™¼*§^S,ýiVûhq3÷šQD¤æjŸ 4GùèˬöœHÏM$è(9çÓïR`Ç£ðŽ
-¨ €
-ÈP
-/KR"©È…¬ ¤6—Ñ!‹Tºƒ¼‰+޹XL¥JÉS‘
-¾,es$Õ¼Rô T{RݻҒ±Ié×-ièT¥î¯HéKÍ!¤ JSÉ—–“+måª6¤…U#“ "e·*FU+¨JªUþ@vBMZ|lžÇT^’ÍàKËÑ•v¤m7Ôáe³WUîUÛíB¥ÀånõÈ~×'—"£(MèìwZ›¦²àª>m²FMn"Wyñº%Sã5Rù]´¦2äiéš Šœ@çÊÓl¹Ê—SÆÜšH™×ÈÆà´yš8çêìP—¸MçΩØÍZ<}®sçž™;§Ô­ÉRnJœÇº4ƒRæ:_î¥øŽÎ’×uU{Õâ¤8eÄ9 ®Š7©ø=]Âá  4fCWïL{“¾EêWT¿VÌjQ
-HÌžfÑ ]#4‘J ÄŒò0k&É—&xÍTßLJhÎÁtù~kî
-j:ÍçΤùÊTÅU3Ž¢É^kúÅ”èLíŔޭ‘cïks¯ 0éà[§zøìß×¥ÉäH·­¢pÎñ%¥u]ÊØ‡Æ!l™ë›J”¤i’éÔ<ÈÓ2ói^~Î H(R¸ÄX3k"/o¼WböµS)Zµr3iZk"SkOÔë™y½Ð¨Ò‹©:„ÊóÔñ3Ó;s¥Ø«îYYºgBúÊJø¢XTb÷elDDPÔ:೓ˆÅ½_Ö'
-V^ÊÞRÖÉOyézãF4í(Ï; ”åˆÏDÁ±õ•C<áÌ%æ\ÑäeÇo¦«”g¯ÊÜ«j^}˜4ªŸr5Ì+U²¸mgÓ,˜Ê©8£âÑ4ûU5"Œi|‘ÝtQdtÑ2r_ft±Nþ–r=BŠ/JwC®v]ûÊÇÐ^†éEŸup¥6seò(о¬¹ò=ž8«Íqæ_ŠmyXfÆ´šya˜¶«¼Sìª ËÊšo\ùG¿,  UDVVy&L¥^öe› p
-­áÔ!ô˜—s1pMБc·&*Àó²úxNêɰcžýõRŸE9*ÖÄùÙÉ‚:Yª+Ãk†èŸ<Œ*€œKׇWµ»ÁÎÆ<GæZñÕŠWeÔRý\/®4„G5ã.Õ;4­uªW«©¸8ÒQшþX¤OÌ+œ¾d°b:û«6òD5ܼ‚¢Ú”µì[Y+à¦^Çfœá×Yg‡bØõáêV³.­uL] ôDLêÕ­ £šßØÆbØ´ŽdÌ¥¬ë Í1 meKÛš8ãÇb̃1ltǺ,{òtŒ‚·t>½f$‡¹å›3ð½x „1|¤zl}†Ù†Eññ¤ptÚɰoE < ®û¶åbY¸/+ÀÙ‹Å…*‡ÎN1Ý B`cß‹IŽÇǃÑ>ÿÒB‘0c\‘½Ã"ø+ø[Å8rÓa|+Uæ^t
-VÇägªò3U_ш9„0?S•Ÿ©ÊÏTågªò3Uù™ªüLÕO=S•¿q'ãNþÆ ësyæoÜÉ߸“¿qgUÞ¸óö‡ÖRŸWí÷9W´_lÿÒg¸ÈÓ§V†
- ÷3ûö˜Dbº‚”ri‹1‰Tø$ E;ý"GÑ‘¿ÍA«€Ï±šxª N+ƒ6 <=Œâ@œz΃]§GäãPª¨M"‡«~¼’¶
-’ÒOÐSÏy0³kÏšÃѤ_É%+†!³+âße§_¯e™„# `YÐÒ96žÊ°ÓF7‡ˆ)lS«a=pÙ…<pÖä³`Ù"ñlÓ€±Þ4ú΃™}Ó÷ØÜbÃÚžÌ4W`éIÆ”³J†_=6ÒZ<º0lÓ€½àÜ©…á¾ó`fßÙmƒÒW-•nó‰}£õî‘„ž²KŽ ØY[ƒ?Ÿe礋&-Š
-“0wÀ×°MÆJfÓè;föýÚž=ÓVœÌñ)у‰ÐÁšô˜ÙwZßà®Ñ¬(ƒìH&!Ê>óÐT"#.Úøë¥Ú4@07 €B5Dê9ftÅѼ´êÊa‡œoòx"u§2þAS Eßæ&ø×eøûæklM82óÝéĬ °IA‹Á¾Ž‚7i€»q]ˆh÷A¤àÍIp¢ÙI°äpФg!Û|¯£‡!(xfT-ìËG1A<߉
-ª™•À
-èDÀPs^µ…f‚ Ö¾ïШlisHÌqѵAj# KħÚzžÄl{ ål£½"‡fûÀ‹ 8pnëLÌ™jèøÁB®ú`“Û‘€rlÆ=øZ²mDf*hÀsãG„
-yÎc§¡8p©-0‚ˆ±0ˆ|Õ_êc›ëÇ®lêÈß8æI
-˜Ãeæ°ÁÕQýàìÆûjèñ 2>õ'æ‚A…‘î¯,Ų÷cÕ™Ä ãÄ+ jr… Ä OD$$ÏÐÕÊÀÂû^DÀÈÍuä†üå%pb‡VFÀC<zœï
-Ø ±ð˜Zšm4[­gGŒlPí±˜-#›F!e˜ÆsR
-„½8Œ@„ÌI‘2ÊÕxaó^”f>× âˆPø¸&
-Eà †P\O£ 'Ÿ¦ÐâØߘ4ô´”"›€®ph
-WÄ”9Ö‚ÚŠÀæGáNÀHð ±Ç‚&òÔ
-
-z5Z«ùi
-¶•Qø+» €±Ö3Ò
-f¼±ði3zèK!ÌÜÙÞw”äó0èíD¬W]ž[
-€9àªÉ°Ú1‹zE" çò£<½oÊJƒ€V$D†®`“ÚC‰Á2-tm^Øð‚• ü¸-¹q±¶èðNÀw¨hÒPQäÆaLmúÀ
-+ÌÙ±A„Ðd
-(|vBb%ráj´.»Œ±Mƒ¥ÅR+RbúÚ13Ðæ€ˆ
-Ä1Þ»#Ðåm,´ÜÄ1i«#rBF@¦8
-1 PøšZVUF_]!.Á•÷Sæ´iÇ1')¾ö‰¹•(ðAýø1ËHò´
-€m–;ÒçR@[›s¼ç
-Ûf­*œ˜€É@b=6Çl{zÛŒ ĪÚjƒ³Èψª’›ö•Ý)¥”2B
-Ú²`ÒU`‹À¬86‰-C†š@
-@oWuÅèÙZ…)Ë!û°>%¼
-¦Y´së“k P_¥s²‚g†˜#à˜Å4Z²½‘r*¹SFHT<€ó%ûL!
->…è*ø,„Ë@Ç ÙBäh@HAF2-”A¢±ç3ƒS^)D>
-™©rTx7Œ9# )v (­:<ì3#XYÚÆ,
-›óu8å«Û @çï…­‚Õ4ß1w—«<A
-ŽÉenN3öYÒ£8Ø$hj¥söC`iF@T±#@ý¬4)ƒ`‡Kŵèó´°èñ9)/e:ô‚ÙO‰´¶`4ø¼v,“±mĺƧ -´e úLŒ7CÖ 1ÛM"P…4‹¤.Uh0a÷ ^­íª0[Þ’¶
-! LPjzC=0Y^I”±`¡Jù2ô«0tR…ŒâØ_g+­v
-AlS¹ EHó’3ÊïD˜Ãa±8嬟ÖÖ›çð|Ç^¨Ã)ÊóTI
-Lèþ¾£ûÇ*y)ÌJFN YÀvƒÎVˆ˜Ë¤·àq[Ïg%Fe'Æb6Íå!Z‡m¤ŽÔ(°:°­ÄL‚©4VJ_LåU<*²9·S½|RdsY®TK„1ÂÉ`Â~bŒÙ%½"¶ü\]³¡q<©Á#y˰ZèÙ«?³ÔCrÙä}‘
-|ÉÙš¦X;:QœÒäê`‹mù0¡ƒ4*ÿÙ*}©v€®7lè _“ŒHcMì
-ý@[°óu
-ôtqþ‡Ìl„E15L¥Ž+ÒEàT_„£Š8¦É®
-
-‹Çït¦_‰,:ìY³û¡¥ýB]"måiTZeñ0ÖÙAÍÈ`×<±Z›4UÓÒR@#f/”.‰<Cë¤P
-8`ÿ·!ûàØRoOÛæ‘iAJ¥4Œ0l*Ï!‡gbuE8…w
-A¤Ï:Ñh7 œVžy¾*5Ä1º¼¿)y&™L›Ð©4ŒÕ™nõ4Œ'm8åC8Ñ`]’Ì'€dˆT×ÐS5“´»&Í×L‹â§ÌÓEuø€O&ÙÄeÕ'ÁX¢ÊHž>ŸÁÌ­®âr\9§zÍ=»`Ç3ÛI¤–¥Ý›šÆô,†ÜO–ƒ3®
-X"F:+„f2M.ùôŠy}¹à2âP €P¤‚Ë ÝùÉByæ;™¼ î ÀÅZ5¤¼;SÅ C\Ý.MVbF‡KÈeôƒ9”Ï)¦§ñ0ØxXzfŒ£àf°y¹à(~×U
-X ㄱ¤óumþPªHLMÌŒñV”®ö&ë@:þ(´û)+ŸÝà8*
-*,'Óc 24ê1^ª³`à
-â#®*Æ€­2]ºð C¾õièÊÓçÐP© ŽËZ
-ÂÊIKÌ á!”Ÿ‰@|\ò$Æ:áGG …*lÕÉA:ø ”¥®’–‘®8*…º®2¤ªl…טÉ$<ŽÏ@S›,¡‚œå%W© KLG¾Ç“à2ZºŒVÇÎ0§ð<ÊÔëºÌ>§LÖæ©mÞ"¾NŒ
-|®F¨¼å&%éD/åð^ö oÌ#HsNX3AFE ×eÑFºoBNŠ;úšH
-‡Noú “Puž
-z¬ðu „GÙ" ¥úü@
-ŒµXÅ6—jçÚèçk£¥/CÙÏÌeK¯Y3S²*šõEæD]õ¨Ùë%ݤ›´‰ Ìv<ÿ4^æ¬×·9ÛñÂôP­3<é6[ÉqÒ=kž¬2:nªÌ©¼UðŽì_…™ÎÄǬTËOÙ-#n¾Ä’ré5ñb¯‡\fí•™’U Uñó3«"ïà¬eß#™½»¥ß#™)Y /ûäóyñʲ쾃…Šº:Ýî"CÝ‹°6ΰ ŒþôSöБj}þYñî?Í/™i‚ 6jÚªýò†ÂFýìnÿ"ɼ8í³ªúÍìåø"|ÄÌbò`Ð?Î. dã 8øÓKš™ÏQ´šÝÖ³~;»7•v8wʉtn³’Öl·;£ÎßÙIK;\@’£—®Vk|<>»¢Ã¤ÌèrþGë2Ûüøç’ˆ¬dNöº —¤Ùë7/ìÕ°«úºõ(/†Y2Ï®uiŠa²S²jѼfI½ l–eßö—¦&;%«Ðù/Ã\öŸÌþîüæ—%³ý¹å0ÿI}´ôå0­KS“’UÑ­y9L^³,Êè?PãüWÊaùË®‰/M9LvJV- ´šå0 pÖ²ï‘KS“’U±ð–­f©ó?«SͳÀ–[Tx\Юâ[¨ÌWá§­ÂÏ{›È
-,ÂÏÀ=|õ_ÚX~¼W“oÙ[,ò•É Z•=X¶"o-º”/Ïß““K´$Zø_–h™‰Ï%Z.Ñr‰¶ä­>
-¼#¥àÜsí‚À¿vþÞƒÏðÿ{p£pÙJ¶;½vrÐéu²§NÉIÒÕXF£Ç¹Ó7<Á·Äd¥-GLþŽ˜ŸýV€l†×í1ËbC]Ÿ^Ü_äÇÆ—¼RZV¥V?X,¯8Xhï,¹øÆ¬ÒÒ4ïŸô‡`ÀnÏØì«'Îb©ÕN˜UyåVH d~ʾo>]ĶÉNÈåB&!Þ’9äùé ’MBœ¥&äŒÌ Iˆ¿"y5”ç‚~Á*©ÎŸÿÞÀó޵:££ãd”ÝÖùÏêÐÕIq|Çæ
-y†²<…œ§d¨h¹£_y
-y¹c]y
-yyÅÁeJ!·;ãì¿f²ì¢`ArVE|IºÝþ?Y©êvFp½…ïSÍLÝt·åM`ªuØYè· &ú,/iÄÀÕ~\õ^vÖœéwþ^qf5€²ØòMvʃnyÐ-º)t.ÓïÜ*xïp$½{`%÷:½vç°ïïN¿›Œî ’ö½þ Ù;̼Õòh\Ë£qy4nCf·ŸóÜUmF™³.ÍÿuŽÇ£3~vÐ\nîŒf¦)é—…B>F ‹÷Ô:Ò9ÙÄýuQ15å(mÒ_!–¿La§áIÒñ>¸„þ`ˆ^ú@Mv_ŸÖ¹þï  Ä3f;^@Í¢T.µ™í¸Ìk™Çmò¸Í<rò¸M·ùZô£4*nCA¾Éã6yÜ&Ûäq›<n“ÇmV<nÓ¥€Æ¥(¡ÈƒP??µC~ß
-F¡¾!r³ìÁ¨KyøGØòwh,›PÈþ¢ƒ%‡FvB–üÙ_’¿Cc©_ִܪsÑòá¥W›ÝÎh»Ù9+„¿z:3wƲêÎüýS˦;ó÷O-›î\T*/»Úü&'zUTgþÞ©ÿ®î\ôþÂÜš¿sj‘\ÐÃ/Å;§vŽšíþ?—à÷‹ò·2åo¸4V@æ÷¿å'òÏ} eþaÍö"È,—ú÷˜,;!_²òeÉ%À²K³þÁÁ0á–$í…äô7˶ Úþ[’Òÿ†ðí«z=eY•óÉ’¬À‚ä®ÙÒ¹fŽg¯eeÉ£äìš0ƒ-¹ùùíýì4ýÓi/PŽG­Ï¢u'ÈLQvkð"ŒÁ4°úïž^dU²›¶aÙæA<¨q&-«Ôó ÆÒšÂÑe jd'$j¬€û›5–WíæAe”äyP#j,kPÌQsÚ–¥u1sÇ,ÓO š­Q³û¼ßÉ^¶­:gœ~Ò9ÓÕúy…<çMÉbÑž%>Jš’Uñ—{ýQgÔ:#
-jºÍØz·Ó]à…}οf¸˜ù…@ûÍaÒ$ŸÇI¯•Ýs›êuþïÌUѽññÈÊ¿X;³Ë*i…Ë÷²£Ëúr »˜ù§AFýìJ»¤\¦×- 6ýãì»G6¾€#Öù»‹òwÍ#-wÑO¡m[ê¿öꢟ4ÚöÇ]˜ìUŠ#.à.¹{)_¹’¿—ägnÙÕµ:ö%¬[€¦Õ¨ËNÏÒW¥JnïŒ#÷+ÞϾ.yýØê§)F¦}vi’HU_½¸}Écâ™+´Î!$ž»{ß"-r‡/wø~ðžÉ¾Üáû>šr‡ïâ¾ÌKîðåßÈÊËZ—–»|«éòe~Çjz|™ÉË=¾%¹Ç—{|?xÏäßw{GÁ%ôø i5<¾uçù|¯ûýöá ™]2-­Ã·È²ä.ßê»|—ò1:#¾äçw.ã/2;>ù/Î] ä¯ñü!ù/¾S)ó{ .…lÎßß±´bì  &¹úâ»ûÝfëÓ½‚õOš­ÎèËÝ¢‹ÃÑ—nö7µ>ÿƒ¾‹üàò²ï¬…ˆYµÍÔ@F\¡½´g­„ú¶·ó,{dt(ßTY½L‚àTlξ pö²È»Ëdp/úã K.$gUdÀ?G œòîÒÖ¯gÐËqÓÝÎ?‡±Øªí´š XÝ}–—4âßj¿75Ïú-E3ð0ÝïÜIÌ\Ë6š­d±å›ì´JtÇË<3ÍÿuŽÇ ¤ætûs_l)+.Í+°ÂÌoJºðe¡`³ÑãÂl¬ZG
-…MJe_DÕ
-¨MR2¹µ·*¿i››HËd"e–T¼ÒõOú½dKb¶ãòZK<Ö…Í¥ÙŽ¹½´$âöòÚK¹¹”›KYǰCjí¥o°1–Ýlº”eÒ—ØÌCæË&2«ŒOٷͧ‹Ø5Ù 9ãm>&!Þ2ÙŸÎhiâ,õŠœQÐaâ_˜–¹d¥¶‹æ—–^mv;£ífç,_sõtfsÐ' üÈH®;—MR/¹îÌNÈ’ëÎì*'×Ë)•—]m~“«Î\u.¹ê\8tþ+Ëh ýt9¿kñó°BŒpY_Et “}wáׯŠâ¿üïXºôoÕ]ª_šû)’}%_²tÜT™ßȰ
-‚Ý)ØtÍû¤!YI–Ÿ²s"7_á¿ìêìtž]Œ³ºÇåù°g¼WEb\BÃé2ŸjË_ñ±¼[iýÒ¼ãc=³õºì/ù8—@Ô9Ó´•¿cYEÀÂFÎååµåÏ«`d)Û½„¯±ÎKù–M4| ·-»t0iÊ|¬qU¶“ýgÏsc;×´?b/½9HÎ`B$˲Σæ~ö5^…€¦[È:—´¿Z,b9Ñçâ^Å5îµ^¬4¹t\V»ðßà³G9Ÿ] Ÿ9ÿqV¹¨éìà‘òÝA³7<Èð+ËÃïßbÔ,»¡öçMV!¢H; 4‡üÇã!²r®Üíæ¾ÎwnÁ¼Vs‘\ÐÃúù§µòcÇÞ«÷Úúg  dïy¿· (äëtÖ¸’vzæ ëù á·v¾ï÷»Ö XÝþ?7-»P†¿oþ±Æò² [–]Œ;Ž
-vÑ £Ðß¡h;ŽU^Sô}Ïñ*<üSxÓ´Ò*œ7_àËøð@ÿü³ÂÛwv¡ya­‹(‹Â÷ÜBDqÑw‚ÂñÔ+z^PØDhß ÛÅ8†û›“㨆Á Ô-‘‚ÆŽÔDþ©PĿܡmZÖÚl„ÑÄ~_Û»±s"ÿ«X©”[­ññ‹þHGñÖö`ýö¬—V\¸q³ðæõħ¹˜™¯`Á¼mØÉ ÷–m8H¤»Äbk{îlC|ÛÐ`”6± ¥J¿ßlÓCúѸÓV»œFÈ£J™M±É·pZ¤îlwÇðï–ü `·v?)TãáQáY³×<L…­A¶Á×ïÔÍj³Ûí*+‹Zîi¥BP8 nsT¢¦0§[= öÚÝ,¬[7ÒÆÕ£æ ÕovK7 E5R mbœ?˜ÞS† t¥ã¾‰emAAí®XþG×yÒœ1cˆ<[71LU*¼ì¡hjS›mœp¾`ìE n ?¸NÆòCàÇp· WÁyàÝ´`ï‡R«;@Éþ2ÀÐ*=íõÿéÉ/°¯n”{2ÿ(ª öÜß ß-I‹iÜkë_ÙCÚ;½‚jÐ q£.Q“;ó:팚­O‹vÊð¤JsØi™ô?%_íâÊÏÝ­µ½3i±ÀDôG/’V6Yoªf4€é(áÇ6,W1|ùÁ"T ±íÄ¡øåÌÒ[½i[J¯¬Â 㱬ò`” ó
-¥íæ`4‡öJ7鵿>[_%TöOéĹgŽ;pÚý”ñ~eèÕ~¯=îŒN¶ÙñG0 .ÿwÌvO§i+óc;XâÊ>°à –
-‡¹(Î,гî»\´þ·EëM}"—«ÿI¹ê9±kÈÕÎñIWËUå×{l£{¡/ì}y¶él0Ú#„„¶»h÷nì;®ô÷¡Q¼ˆ›O¬Z’§ŒÏ¶· êàKöìâñgKºTD9ßÂO󅘓Yˆ}…Tå ×ý“ÂŽü§›rl)©7ðžºUlvN€e•Ó
- bÞÝK»Q÷L®Ðƒ?iv$’e\§5´ð»Wt]OJ/’&´:êþ'[áoíÝœ;Ý™]¸ïX‰a«;˜¦zÝ;PgÛ j7Ÿfþ Ff8u¿Û»@ t6ý?Iv ‘‹À\æ"0ÿ]­–ñªy<ÛË ¶—Ò±ÿ)²þÛ}ö¥ðnÑ gÅ»¿dòÝÏ ÚMJì­¸qÿ Íqwôîëv÷ü¬¬Ô|y/³Šõ^;Í)ž™˜Ünv“Ñ(‘cßÞÏ>ÚoÍÿ»›’ì7ÿ³¦áÖvkv^n¼–?Ú$ï-°`9A³0Êb,d¶ÖÑ|M^<ª^$mÂm«ªlìÐÁ6rÓ?’nkJdkŽävIÒ£f•˜È ²,'aâ¸uõK“GL•ðy,ÔœW°ÆF5v]h%GhèQ¤Ÿ5“Þ¨Ií"ªÓ8Š‘ëö8\¼åH?`'BùÀ‰½Â£^\¨<ðƒtj¹m¤„ 6O ÃöñƒÏ'<h>zàF€Ç 5Ám#¹–
-‘Ï¥:z@ˆ
-á". í%x–\m^âòû6ÒãˆBF$÷Ÿk»i†â5¥©Tˆ9Û‘x„ϼ"?#3Ò  c#„¬^¹|jI‹®Ú÷
-Ÿ–Sò”óæ†( 4+êqú6ζR¶ÎÆé
-¦RïÝb¨{ó†N©T˜Ï×D:ŽÆCÜ#ŸÍT!R¦>œHˆÛ ¸åŽœ¨BÊTðAòŸQˆ™b1Âæáóoâ\7ä‰WKlVÃѬ¨a¦ÕpÒ?1Fæx8²(bD¼^ŒQ ‰¤SÑ¡=ÄkHC
-“/IôÕˆ¤ÌåÁ0V‡­h3—{
-#q¹dr”`¶ð\± Ð’ J¥šÏÄß6î8X ¯˜ÇûÉ#>d1Âr)PSÏ;E° t|Þ)®B ©ÓÌÎ…‡šú„)ˆ
-;ŸÇÍA2,P]ðÍ Lêzk }W89µ«ÒJæ!|§°£8´n<5Ô£
-IèÇÍá'ÒÁ áI4ÕªÙíPQºàòööI§¨@>ú*³¶w+Û åñ¨_xÑ+vþ7[ùNš'É 0ì»Fa~ZhšƒÑ~¿9hôOyéiŸYZO=4#kúÕ±™Ÿâà?åtKz¼`Þù–µ½×zý¿›ƒá½SN±èÃ.ÐáÃ3N»è‘ '¾­èìôú½ÓŽ™Óí·>%í,3Ã-c~+]û^êd  ˜c'=—DœMŸÙú-ÿwÎÄ×Îw­íe¢¿ƒ'm²0þ™«ºJýîß™·:6½`ŽFòZãá¨|±’ìçñáÝaCë¨Òa‹eeÇŸ¾/vÎ|“ãyå2ìÒáÁ?K¬/x »ÖªËâ8r0ÁVöi¤%~s]‚[^¬ v/À C|aÿtÚ££,tQË%kÝ íLdõ~x5‚ 'Ç Ü,Ü÷% 5_.š턞FÆ~6Áfr0ÚtåKΤj¶Ïè)øÔk$*Xsá
-|¯Ðö»ÍQRØÇZ @È"Vª`¸ãY2<Ò)¼H ã8Žœ‚þSÑþxT8ôÇ'ª©gO ßN Á×Ñ»Fðe„/²:ið·‹
-:xöíø¤°Ù쎛‡Ia»ÂKwãí³¤ÝëóÎàÅyh𣤗 ÔXF…Ôi)EŽ]8Ð ’ÖÿNZ# m¿Ùmʲ‘Ô¥¼ó©üx»9
- yX}ø¾Ÿ®}®=n?¾RY>þRÞY¿ÚScxÓl­µøãÛ­z+øýFõÈß»w¿¼æ]»]y~çÃíêõ—j2¾õðÕ“«G÷Z­æ'üÔ¹]?Ø<ROvìRS :¿|¸Ûyÿ¤]é®ýz}}pû¯qysçÚgÿÍ{OŽ<k-¼÷êÝF¹×º~|ûÁ³{%qü׃Ž¥áW´;·?Ýu4ÆVíÉðL›¸žˆ×žÝ¾Û©–š°¾Î³7Öï$•®Ø>Vü±¹¶Q}|ÿêëú8º<~^}(ªý÷·ï¿j¿½ëî_}'Ñ>ì­AÃ[WqIÞ†¯Ãß{8O+Ÿn†ëÄš¯Ú›¶óîê³Z©yÿZãÊí?ø”o¼—XdkÍÞÿ¿Ç¾ü|ûaã>}ºÿºþT5¯Þ©PÈÜ?ÜÇÀºoìÛÖ︵_ž×îßk|þ^®¤0àÛªôhTy¢ð.€sãÁ l”ø\©ÔöäT×’á¯~øgø±UÞ­}¼];(=ý\o6¯ÿR ÷_þo¯½yYÞªV¶k;ÏŸßÝ=´Ö*þ»{j2ÿ ÛÖ÷œÛ¯*þ›òV£öñõ^µó1,Ý;8^;lTn90?ñ¢ÝOŸí|>~ZÞÚ¼õ´Q»Ù~ªæ†'Zñ>¬þè¤øûí__5?+‚†QsãÞîèÿÊ»OFãYÒ¦fÖ˜^ˆ7ƒ+ŒjvÎVud­Õÿl¯ºîÿZ³mx’î¸ß¨wܺs»ÒßO¯ÕäÌš Ë ¡8ç×£áXÎÐbÎÓ“ÍGå½'Žä˜û·Oî}hÜ8xZ,Û÷wÿtoþòþ¾Èät„ãqÒ¸qíäfõ(|ñ©~{³ØH96À}”0;õ6rèlªãk@ÚÕ›ÕãúPÜk½|Qº¯§×`û·î« Üÿ÷¨¾~g?ž·$ñ§äiÕZ+ï>kß ó0®U6ÿø4o´²¥ÑîÑâ
-#.÷@Wn6><ûãnãÊ­"h1;Ù¿±¶_ÿ,—Ú§×W_V;ï÷6ê­OŸ¯)Uf˜ÁhûtwÆ4;n¿–î øb“hípýæ¯ÊôÛ~|ó¯TÇMx[öÕW×oÄÕ£ñ‹?kOŸ~®˜Uö’ò‹^mkcçý`,ØîƱ3ù”ÛÒw¸ûÜîîÝ_ÿÐèOß-ýßÍ·à„¾:©·îì–*áwÝðÊþa-¹Uÿ-µ­ÐRz2ŽÓ‰!+ì¯hËpÝL#\Sômãn£ Ì³o|è¶Þ/={ñWÇ–XëÁŸßãœdpMÐRúNç$ƒkBVŸæÐu$M¹Ì¾ïûO©‡u‹ƒßh ^®}"ûèÍ“Š4cÓyJQ].ÏB:ÒìOýöWíi%¼¸¹_ù}ãí­ÊïkïFÒ¶Ÿ<rÄœy2}ÉöçÅÚ㢙Nx8q4ýåÞoâUws·¼õò)°;ìNÅœé@Ns*Ô|> Ã[z<ªtÃ÷Òú·ÖRûv ÉVíѧµ¶×ï÷1¨Ñ‚OwFNþo?ŽoßóŸO¢Ý<ÅI¹]I˜GåîÆmè}øÙi½øuËÝxy%&Ou÷V“õÉ?Ãéwÿütµzôו»0à½=^ýwE ·{¿òéÙmpD¶|½Aî¢cð¾òÉ}p%½¡™Ý¾Û>îÚ¸LO&|ä°Ò¸_ÿ«¨±ˆÆûw·®6ê½1ìJw->ŽgÝù¥ô6­Í'•ß·7¶Ý›?§ŽÿX+ÿþ|çúÚ|ãõGæ¸ÍŸÆûÛöæI±ûh¸• ¦žL»rêÙ?úÉÖšfÉÆÆ`pôÒ¿ûìõ¯ò÷ì_ï}@ï®jÄÕÇî­“Êo\±;/‡W&Öàíûr|ï麾±ë.vÊÒ«ßÙüߓ߷nÞñA\½ÿæN»ÚéE£±wóÊRêmÜßßÛxýûíkwnït@ùÅ%ŸÒy&€ñÛzíÉàÖÅc³s¥þPµÔûwY¶Ýë†åkRbæ¬ýë¥Aǯï^c ¸{ÁìT;ÃNˆQ…õ·`?Ô?W§0fðò ´¿_ÍÍ»×sUŸve“»Ntå9ìý›lÊOÿpÚj<}Þ®µã;Ì|7þüô_íZõ·«J­÷¯<,ª@€Šž½~ÜM>\Khž~Û.UºÅ ÝéI³ÃZSO|þ2zWß{¿öxeãsåý ­±Ž4ßÔ Yƒ™ˆ£Î9¬ï—þìLÚ0Rb¿•¾;éëÍC°”Äëg';“º[µ÷½zR¿µ¿¶É=87ë­Ûö_eÿFü;ˆ¿×‘²èñÞÕû¿¾¼V{|Üy[ ^½)–¿µ}X~±{»ûeíÑ;Qùä´¦©¢ʃRíñÛÍ[hl¼M@:ßß™7øh÷Ú/;½«×þ¨À|UºÑ/wjOnܼ!½÷¥%q¸ö x"þ¿{¿ìÍy¨JôŰ~ûVx`ª7\«“½ÊûW¿ŒFúÉ›°Ä‡WÂÑf<¾J°[\Ÿ¸uýŠýøí£û„BëW¡}öñàànçúïÏÀ¤»SnÔþøíÖ<Ò&Ú·­µ{ïúoÿúZ£W·ÄóÖ½­©&÷’÷7?É8ÚÝç‡÷:õ;ý?ŒSÞ ïn]ÇvYÂÌpÑÕ!è’gGÊù5|ó¨ú¼úê×)Þ ìÅàÊ[0›?¿€EÞølX‡„Ê.Âô¾>±ÖddÎa> ÃϿݯu7ƒÔ¦E|õJí`çC¿Úù¿_`l«Ü{ø¸?‡p]é¶ú­“øÙAÉ)oÝ­?ݸW91-oÙýƒõxŒ2y£,ÞµŸ×â¥úŸÉèÚÔ|Æ×wAï¿ÿ£Ü?Úº36É,Ú\’_ÿJƒúõ±Á%„Þ<‰?•ë»e¿fã^íà÷!hd%*h´¿]mTËïÕÃÿÏÞ{¶7³‚ß÷yð’ 2ÐhäD‚9‚‰™ˆ ù~ñÿÛ±wlÙ3²ä0–,Y²ìÙ}<^ÉÖÕ½w«NçF'„wdï¶Þ#^ ûà„:UuªêTÕ9ª®nÒµ\*úšÓ¯’ ¼dÏNjÍòFq¤ pâ•ålú¼û˜MöwÄ.9ÙK‰ñÈZ<Ù)/æ©[Ù¨¼í¾·•*ì/Ÿ—ë i¡X`”¥!šé;^Ö²g'cEÛ[Üö¸9ꄳ齗W…pN¸åòGA8z‘Èõ3ÇÔaõßa÷Sßû}êÞÞ‹ îÆ”à¨î‹ÕÛá°j•KþUÏ)àbã3ÿ¾¿ŸÄ—Ãeؾ^/QRZ§}ÀçbÕN¢Å‡“({Ôû‚kÛûЧìÞÉVnGÅ‡Þ ¢ƒ°)Ø5ýx¶sQ.<dX™|ý…ƒby«¼zñòL1ñ×§beËÓ#Åñ6ØöÙåPjv½ì«uÎQ¹¼FqQìnÜ¢ª0Ê
- xÊÃ|þd|°~RQå%·OçYP³3¯Ù­þŠ’E1>u¢
-(RÃÐ%·u+åâáCdôd/¤èm™9ÑÝ“–ËõR;þ=‡#~`ys‰ãÝ2¬Aã ×Ë=øô{Èï$šðôD=¦wƒ,ì¤'kn[”ªB{~]Œ_2¾S# â“Ådʇ€T÷T©ÝÄ‹ÙjÿS¬ê¡@ÇñˆTidßÈÁ¡ ]7·/·Ð]ç&ÿ–È®UB8Èäðp!#¿8J‡6ÒL•&ˆÝªŸÊ¿½õï5
-¼ŒcŠm»UjQ^¥/´Èñ/roÍ.žJ¬àa •;êÕGÅÐþgG””^ÇÒ¨•û ée­Ô^æn@“qÊ¥äQU+l|VêDQ^x_[µý…“e! `8v)Bz1‘)ÖÏKÁ}o
-=—#z=»<RßçÙ·²_)ƒk;6¦;$áÏÂ^)uO6”àÖð2%3Gà–8¥Mß¡¿Ê^ôy%½!´b¥òÝ[”ɽe¥\²2áÑw¸ìÛŸèÓ÷áz7½ös>ò+{Þú|'R$òäL»«æ–ã\²ÕTl „á^6« ëõ¨õ‡qw e½½@1ªø…t0LÆåá>éÔ1ÈÛÇåröüx|Ò±Æ_Ž(½¨ìúœ3 lìæŽCYX—ÇÀ‡²‚œ¥öxù.— G–Q ä4èÛÑG7{ít¸³Ó›³d"S¨ž®:˨a-g7ÙÛâÎÎÆ²tX¬ýÈcåæZ)»~s
-bgâ0H1¡Ï6pùËWØsú¹£·ø¹Š 7/²CÿÅrqg›´_É÷Õ»
-O ’2À!¨@N&LŠÛú lÛ…æk1ðmOð,‰]IœJbR×*g€ƒËÄÉýÊ
-78¬fP{õfÖÐüR/×\?Ü-Þ¼DòšêÉ}Ø®BJ\^ËÉ­Ký¶¹§üan•Ëdž\"qÒïèZ­9‰†nŠùјØm•«x½Röí䓹ýÀ9:Ô<úxGšþdJ„uyȼšÍZÙÎíN©\l]2FM´²ë;û =Q¡‹â¶ûR™ÏAPÙ-{Q¯,W+ÉýZ).Î_iµO?߆s'Åa@¡ Á.öŽÚk@Ýsª\ȳ,¯©ðT|vûP‚^ÊÙ:ÝQo[¥Ð¸Ø*ûNܾÄùóIƒìá†<¼Šè—ðî<’¡sì ÃÏ…bÚÙqñqåz•oªZ¼Û>ÖŽ·cy.ÛŽ(çšèr‰÷ÛÕw~CÙ9/äyÉýK·Ÿz¸ ïFw¯?ãÈ„·cÃX„É›@Fs†‰ßÙƒ:Î^ÁŸ¬K°´Läªìa#ðŸýá–KˆÖÖ8¾‰6qM$8Ù½N]ëXòVz]2K¹šä¤w¬ôͤŒjÉ®|ÖÞ€d(QÙe?úÒkEÚ½7t¯Ö:xk«õñ
-³æÇcWí7¨­6|}î·Þš¯~ÓNÝïuÃn܈&º=
-îÀ˜²@Uûxè-ɾ³“‚8”=aƒÅòŸã¡<è½ç£ï÷¯Ð xm3q!Š?, ër±÷ý>à°ö@ȵzß½Ý'ï¥Ô´Âî‰û8ºz~ŒwWÙ;R?<è½=·EwÙ¸ˆ ƯuYŸjü˜·ô[ëÀpžžÅ•‹™a·÷Ñ3† Áì­]•MûĬƳ&Îý¦ãm?ªt[à¬@®p,ÞyþèX¯´°ºµöÛ¥Zâ)z\¯ý3ÐÄI¯o=N¡¿¤Þ)†‰ b4Ê„Út·Ÿn’yÏd=`1(!×ôZÍQ½ùLx"ðDýK[A(1[¨§‹?Š mǶT "#Ì
-β<ð>¢JÁt¥˜YÌOh†‚"ºžwmRvÐàOäº}WJ­È‹nÔA»m ÛÏ=•x>^höùðÑ箜è~ .©Ÿ‰è7^©Ö¿ÑÊœk=9
-½~ÛDz&†&S':ãY-ðsst
-Æá;G–@D„ ôìÎÒµïø|ÿàÚ¿ô=ÆB2zôyÛ  ßêw…r˜©Xˆ¬®õ<zo¢È¬M‹¢ËöÚÄÊ7”¶Cóš’TÔ"ׯ˜²’Þ
-º¶HRýõwõ¨mT–Fm£®bÔ6j·Ôvƒ²?xè}˜.Ù—4éO ê„®ÞPôOP€´ÌEÿœj>ÚaC¸ÿð\h4‘°D¿Hd±¨¨Ww åw AK{&ì™×EÛï_™ñ>¹boô$©î [€~<½‰¢Ÿ×Ím±ü™P_ÞMíü¦ßÁ=îíÃö úöx&þ„g™Ò/褑vòŒ~uZÕ”H3žŠ™×Tf"n¨ñu[VæI^Ëé‘c K=GSMw;‡&G÷do2åYVT¦õšC^ž¬,ŠãûœX_q€?m"/VªŸÒVï7?DÑÝB‡Öàž?^߆#š^ÙÊ7²|¨»$ru*Ò|ÈÃØªMOÔž€¦r$°ÛöåT{œEãläaÐýË<–õùÁÄDq"¡»×(Gßé~ %‹oLWúPMöãQD«Ê¬²²ï`Ðk—åoųZ1ÊÊš WeÔSÖÓUð· {zJØ‹hÃNU›¶7Fg0&ód4x¦Ç±•3ÕKþhÔò-™´L‰[¶aPdÐ
-o!+ZRµ×&Y\…ëæ­ÓZEa°—P]¸VÒ¤2²[†üzžBí6ì&›‹ÚÁ\‰ÇÐ<†™îÏCYȲb1ŒŠÙ`½jì²Ã×YÍ¢ò·Zo9æ e?ê³;ì16h1Øþ„Y5G²b0Óšµ5U[ŒB‰,67Šé¶u[Р¦€£nØ
-‘è©ø-£†ž„´â…±Ö½ÙE[Jz:’°Â©ä JI×6WÊ–
-7µqeý²þ±Uy;»¸ÎUcé[R_ô瞤˃Ó|w‡?[¸$9œZ×ê×jתào§.pþÛÂL7ûž©fêòhæk•>a®ñj®OÃLƒOWùû=æ8±“Í„àk;ÌO­zP¦ÖPs³ã'™ï ÷äéB/üºÅŠÏTôâ5¡­„(9¸n^Å`ɱ°`"¶Á¸’fܸoÁ×Ê›
-f70x–»Õtš}½+ä :½òSÇéîP¿ÓðõN§‘N]í\ï2ë†î]W·óF¨3ïER¯S—g¸\_?¶:I]
-Æüׯ.—oÆ=GÓ)Ñ’H· Ü‚¦sgÐiãÖ¤ÓŠ;nÜ)ê9
-yŒUÍ5YEéÿZì´ò¦ìtÃ}£ì4v¼ªïaöHÑigm äd¹["ýtB鿯ßi¬Ñ0ît¹üH©¨»U¤ƒN¹”þ[F65º<*
-šEyõÖÍœìZ­_h·çò3$ZÆàÉÏo=`,ëG23â
-VŽ?¦–12TδÈ.Z®LÑ]XÔƒ÷ó³d¼"˜lŒY=º¹ê­Ú€¼9Ü [Î yX­¡Üùu±–†õ4BZÖSº.ô•H³Çæ]ž)Vã¶D—n†© V€•5A(Ó¥ÊÒõþÈp<d ÈÛCøçJi6€] uàU*·.Uêõ©±«ë;uSsy4“SMízÅtjÐk<  „ê6ïNÛøäv$ÏÊ¿Ff¥ìP_½MèNÈ¥»Zª #*<—ÈP…çT÷ ²¦–ÕËDz¹þœ0iߥÑ. 2¿„6ò>4i¬¹2l̰)iGÖÐ]‹éi鮹\·1g]ªSÊü0žfYªd°–¡Rˆÿ#¬H1‰-vY^NŽiÿ\¢up£¹¼KâFô©Ü$CryT#KŒŒùdò—©mýI†ò>),¨†˜fI^“}Í’À¯O¦{œëQìbLÙ`cÒ— p±SQsUF¡½N»¾¯É±]éI’.ôŽy`µÜæÀÂùE͇Ä[G— %ÇP¤S éiÅx¯ÌÊTk½yT4"Ý„`q7öšÊüª´éì¯ßÀ%oVó7Ð,é5åòLߘ•Þ1Ù”Ä-uSãü|³’ë¦hLÍi焘š£M 1Á²% “¿h„ÕŠkI¥dW:–ec—gb´£- Ρhõ©à±ªY>& Øú²BU«‰ÏA•Uæfœß™BQæÏc'Wr”ñ¸<sCdžÚ粄NåàÝ®Á`.[C”“ Ø‚ýešTñ4qÙŠ°ˆŽl9L É^ZnØbýº[Tþâ.6fÈJJ²e_åÖ”&ÇÜGJ78_q4]j£†B†©¡Š[™‚}¨aÚ^©ñÙ”rHS0
-¬”b&Ùm„˜Z‚Ÿij>ó©¹l8¶'¶åiÍ„öß·©îðõ|Î m mt.%Ç3µû°«©Ï˜ Ô‹bAÀÜ ¦±Ùk
-v
- v_9ã3)}IØ
-À„g<ŸP̪ۼ kNE­ö;Ã݋ڣk{+6FÍÏ“
-¶‹#~®ÃÑ:íÔ.GsYzh
-hœºÌ¦ò¹º8ÓZÊf8’‡å”™,¿WÎ~‹Y3Y—M6ÛèÛõ~Ðc3"í?xgVU«V Úã0–í„§j¯Û™Û‚´¢`Áf'ï–íSŽF$z1&ChlJ«ŸÎ^(Yzïý!Ýð|zùÞèøØüò=hXÆ^ .Ït»!4f¬>î…ú6XlläÓ\î®Î¿‹Û5iYìbçÓË÷z­ÕŸ7<7ß ¾pÖí˜ì†æ{á$‡i.ï2Ó{!º„‡xÅn8áû2…;’zöò^(Ò¾‘ó”ì†aÈ„`\·†ê(J×$AX,PY°( i{ÂÎÙ"H’.4·²*˜òZ5Ä><æ+é²iVŵ´E级§²Æw703]›¸Ó II¤
-»¥òÒQÒ":ÛRC³-Ù°'*i­¡É¶¤ò\³£ï7´¾ôS—ÒÚÃä/^Íu#»Þ¶ØÔçªñºLuzƒ,ض…¤aËžlt2 ÆäÖ¸ßÚlÌ@Ä(D¢zηR/JœˆJ1$³ðqñ뢵ÉdŸx§pþTÙsŽV˜€æ#ãêîp2|'Gй<‹‰¡3 “"†æŒ¡3 Sœ½ÎC4 “¢猡“:Õ “=‡ç‹¡3 “£ç‹¡3ì”DÐF NCgA§Œœ'†Î<‚NÃ;s yÙÅC4 #½, †N‡E)"舗Út1tj‡dã8 ¾F×W{•rqVÖÜ÷Œ’µ¥÷`m`帽Ùò™ çÄ‹àªhåçb×Ät°¦ë:‹¥àt0/¹ñßר—Ü.œø¸²‰(›IO³€`0´e͇¤sÆgÒXhÆùibF¬#çìÏ/bE/¶®‰à1’ÈG 3˜ÉD^#ÊÉSÍÙç5Ð@ã9<K
-W#n €19×J ¦
-ë¨Q'4ÿÇ‚;2Æ´­òƒµVö&L»&ÊžAŽ&ßX^›¾ Õî"VÚ«¼Ò0ÙZʬ,Á>Vµ'#Æj˜q¬5í[ƒÃøˆÑ’ÕÚ2JN³½I.U=*×úŽ®Ø•#™›a+¢–#k†Q±RŒ•FŽ4Âä›áÇ4f AUšŒ®Õ 3å:ÆQZ¢™å1’V—-Š¿ùì’«®’ˆc0(ïbà¤=ÅAPë•¶QÀ*2N3$Ãxd g›Ê"c2$vº]Ì,ÂÎÌ"#æì²7(‹ 8Ã!MæîÈÐÛCE†]Mõ-t:s‹Œ„côÎÜf‹mC‹Œ‚ÃØTÞ·§·Èèû05ïüS“,2zÞöÃÐìZdLò)aÚtÂúk5‘:ƒE#Ð,-2.;€±ò´· Îd„7]˜¨‰—Dv¬–…++o;Ârg1‰™SÚ|u­ÏÕÎ<FÍÔdÏY#Ÿ^;SÛôÛÅOÃý¥¿cËuÁ2|Œ¸.XG ZÅÕÙqrYÇÕÍí»ÞÇÈG³›-Ep‘ TÉö\õ ç¯æžùŒ=²$Ï.‡³Çé²7Hq‹Ž‡›/ÿ˜Ýx8 [P<±]Ìn#ζ‡ê\ñp²œ¬Œˆ›sVñpAgì µÈx8b3 ÕXT<Á±‰ˆ¸EÇÃé®ËÂãáLu1ƒc´¤Lw@g/V6G Û>‘$ŰÙÒŽOä„—Äl´:Ox½ì yÖ›_œà[™ô žú„ÛÑ(ÏÖ£ÑÉrFÚ™7ÆžoE$B+xkŽvjjöÖøÀÛòxÖ9ÊÃ6ó@>"ÕÂBÌÅÛ- ‹KŒMi)Ç’’aéºa;œÔPxÏ›å‚ìá ÉLÚ±Ì-c©½’v¦&C½] Û™Ÿ ±ƒ½Ð0›–¡›56¦N l• -ýi’­çÔØ°ð™¥(=©PëF¤ž/""õús©ÐØâ"R¯?‘J/Ç絑ø¬^+ÓF¤B;3ðMÝx1‹p~›£¡ìéb–íØI­öë3Œß1IšjÏÉHéuƒ "4A†iŸÅBØõ¶UÃÍëÑ£
-§ØÅìxô¨'i;Î*ôbBá$ªƒáf³[Z„ÂͪWN
-g˜ƒh¡¡pÙ
-Ççë³ m †…ˆYlµŠXg„Ǹ:•ƒ„ŒðÆòXca ÕÄe@Æè5ƒ4†ÓË0­¡:ɰãhôB$jëÇÄu£ü~Ü«àfÍÌ1Bò‚6÷,@‡ü­qºè¬º/<ñpõ(^–ÏŽ³ÑQ¾îò”·›w›'ÅWºnŸWºÛÇÅLðød³wäàSå
-v»3 v[åŒ;­®\šÜÇçÙÞmuzdÞ½3M§Ê;ªT:-«Wu•$,> ‘xãÀfÔV=¶@©|zjR÷tÎF‹ÁtoT’·N˜s#& ¢’x„£³¡Ì|î-]nµ,€5îWŸ­ÒþÛÛ¯ ío꺖[MŒï±2H%näseÚS°ð'Õ;üÒ±õÍy“œjHÂ=r“÷ŠNk]ÒÞ$§·t¶¬pIϦ†”,½k=Ê"¸Ú¯Ïä*³ çiK+Ü4—ÈÎÏòÞ7«ËFlÍÏÎ]vCP{6î± t+—iÛôҳʗ¯çîjv ñ-0šn~;Œh:==@Ï
-7_4jjB,U~˜é£éôl‚ÂCFPž!šNË0–n!‘–ÇØ®…GÓY­M§çH2E†›Ñt¦zå¢éôÎitÏ^犦Ӌ¥3<™9šNÏ΢Îo¹ˆh:Ø‘…FÓÙÊs5w4TYK'g\T4Þfäò,:šNoHòiõ¢¢éôbé&nÌ™;šNoýzY`4^Sü ï"£éôÄÁ‰˜‘¹£éf„Ø”Ñtæ[T4­(›¹£éìÇXÍM§'yjb«M§ÇpÔ÷&,"šNï´ql±ÑtÊÄX:cíuÖh:½u6:™=šN^!ùhÅx™5šN·eÍM§KgÉ5s4Þ„diÜH(ÅAÍ«
-!­hÒ묾Ív¦Ùò <»H;³Q ¦E„ݬ±ìŠÆŒs Ú¸]X«“ žmšïÒö³bcóàc€ nhŒ±å®Ø» AùÒ PNuß«‰Òš_ëA Ï‚Vç•öLýd)ºÛˆL9ëM%IèÉÊØ·…Ý`xÖÓ2ÌFûÃW[ YG>®æÕ
-r–â¹N«I;vâ9­"¸5)Šg ±]¬«+¦¼ˆGC z 3Ÿð¢ì˜dð~ZF¦Ø$Ãn¸Ó‹¯l˜‘ÏtÃÝ"î­¶¾áΖ4>÷ wrä£þwÓ‘Q¾ânÊ[H\’úŽ»9f¥KšîZºn¸sÙL’3Û wv³š£“Êü
-hy—ËäúD¦x7Ï C†³ˆõ-3ö3>Ywy¦nÌòòßi fy¿ýq1‹„»HˆÅ ›VŸðÎhW:TÞ•6} ÝÀɬFMÌs£žZê›6
-Ðn Ïùg´Ö¡ îGž*
-PŸÕMÆ
-Ëö^âé y
-Ͷ/¯h¢¦PÑF9Ý=~eáíIˆ¼eü\º#Cì$Â÷BùW“óvì)…RþÛì:u¶ª$M`™<C%æ¤ö*p~h/*·«¿ˆ)ÅéèÊp#xº>à¶Nc{¹ÄMÇÇë•yÆyìð·qÅäÞ{õançüü^F/Æ??W 
-S¬n¢$xÎc7S¼¬Ñ<ÚÛûqòÉåaŠo§Œðt|uKˆ)ù›w;îgŠ ÷;GAöUjÈž=F
-ë‘}<¶Ÿ6¶³Ña?Ch¿8nìë’½æÖ\·ßyE³Ÿ·À¯[Ø&´+}‡"¸$>øz=Ä·Ñ`é좊 ¼ü˜ã´\®InÁ„¯‰
-RÑJ6ˆë¶+/</›¨õ
-®ŠÔv%]àgÈ]çÈZ¢æÔ`×ÜÝM¶6˜»+/ f/[¦¶_>ül>zôJ5ÄøËÔÃ]€£èÓBôù ¾…½/nMöaô€»???‚ê%víy5ÚÑ:ÝŽ*‚<-Üí#‚šØ»Âæ×ÎwPòˆñƒzn½—1ra`Š"ã0oðM ØÇõ2ºÂ²BŒ¯$éàk½¹I3ûLÃ
- ktûj£*XáT€©ïÄè úE0+Aöeø3Šã\btè.p}n4«¸y„Š Ýzîé±ÊXø¯`î7òuè4ꥶG™ès([FÞ~GÆ@ Hò",ÎCí¬¯&Æ œx…]†Ö*ð)b×'{Lñ«{ò3s-lÀÓçM+ÀTCt¥PÞbs¥L9¸5êÅØ\ Ueеp™Ð©Py³q Kr™`óI6~J…M’Ø@üä²ù”?ݽ‰±‰:¶ª|ù>ž.°¹ÝÛ; |)^ml¾tvÙµõ+”“»­ZÛØas{™ØÄxVØUÄË]Yx÷¨í­—m@ûc`[§
-òÁ5…+ *ÇJ>ÀzÚïa Dtng£ÀçÒ¨µ¼Ð<²
-Q®Ñ@. oÞAjÊ5}„,ç2 Ûfüµ@8L>µr€ŽÔSrSº]ÝVôgŠJì[ÚTºÝ¦+± »V:ß>WNsâq„@aä6%°úˆäœâ“DöŒ?|»Òӹׯ4èÐS¸ÄÜ—.÷Éù~Žn“‚ÝÞÍk¬’$8!×é4ü‡)vV‹À7Ž`]*m6‘úã¯MÄŒ(uÚ s¯0¼­×d_©cUa3úB6ÔZªTw9•!KžáU訋ñzÞæ ¨ÄÒÄFæXÑDí:Q7ñ´uzÀ
-Ux£8<µ`_¬:òÛéžÊú€2?Y>£”Ãfõè¹U&¶Bê›<·¯ŸB'¸PLèjÀ¶Ä ¥iÍ™xìSÜÌã¡rx£­OQeβ²f¬IšÄÇ­ð9ˆHRN™l{YNÄ„j沟#ã&î~ðê¿/suC–ä䉅 »s,:1ˆ \“L&ù¤&.Ìšhô¥&n”cP6 ƒê\Œ¤TbÚ1Ü ôÀu±ÝDk8#(¥ì@•'ƒÕP¦ŠBì¿îÛBÃ;ºUš´Ø•߸”ëQåU½žÛp„d’$k“9é–¥®Þ]Uwme½Æµ„YkånªGšÕ?PY&+Ǫ¯°—)¿¾¹U£9SU>hôÔ~}­êý“ª±ƒ×±jÈw}Õ×Ö§êkWÕTãi¨^ýÆ«ªíƇºíjÜñ²òëåÊŠòk«¥H«û©†XëI5”ÖëPõõC5ÖçXTÒª>Œ3 ¢VW(ëÒf„«Ï _ܰßî¸CO/'îÕb²%}J»CL¹ä^ú6Ü˹ÞôÒˆ{msŸÆ·ëîàáò&V)ºƒíȶ;œcëîÐîù…ÛÛ?À³ð¡Ûÿüryà?oQ쥎•ÎñÕ 6Q€š'a·×·ºé^‹ÕX÷Úpð ²1OêŠ4V|F3^‚
-H1¼*+€ @Ðx%}7 Büj–]»oo
-Œ‹+Ñæ‰°Cn¡++¬äÊqÃ.Î÷È%‰¿·_ìù ' îâ5ÈW©ä?9håqÇ@‚£P³x½
-–ŒÂꮯ!€~òú!æ"ùdÑ¢¨XF¶ f¨íýë(›_{«SÛÍ:s³ oB•<‡@¸&VO6·wRcîAégWÓt
-@~´Ií¤›Yl{‹õtØ:ãÏ®·„¶¹Bô9¾/fJŒÓ>ž™ìüJpÄ«qÉ«¯<î–©7â…=%½I·k©*¡ýjPj¬È¯‹Ü˜^:
-é×’¥7.ùÈ, ØD}x/YÄ&ÌsÅÓ¢f})Â>$ÿJÚ<Ε§ Gá =D£¡¥-ºšàÛ ß.H"Xƒ]J ûÝÇ Xä'~Íù Q¶ÞÖ–Ñæ%Ò!@”]Mb¼P­^syÅùu)ßñ¥ð7q Ý{XÐó›}ôŽ^6³
-ö•Í
-Æ’‚‘àÒ
-¦b€—ʰ-ÜøaÎÕ}ÁÍxeA@@›f=ãZ>ŠlïdS(ôÑy[1ñwÂÛÔöÁ~Ùq vdªÊÜï=d€'ߟ?£˜½äî-ÀþÇ ì†µ-µ˜§^’Tû¢Â® 6mWßïÕQòLÒíðã–,!O>G^¨˜§Y:’={ñbžfuyéB¹¾„@l¯o£À­sŸèÄꢇÒ‘Æ·¼¸´Þ„b|Rß`Gÿ… )¬úJÂÔ'ϰœU×/ SK‰`$µ$u[#¹ôy£†g6d)PgžkLñ*³-´}E퀖@q6vsźh÷sYUJUcŒ÷û¡Óý2ãÇBô©^b>bHþõ¥ÄÂtU·©7aK€½B+ó©n[0Ðx­DD1ÅíV×3b×ÎÞ7ð¾åM"Ð1÷þ‹¢…Ï+ëIL9Ê<„»ÆÇXî$e`5õ™ÐF)Ü©W2SF‘»Lô8j»R^êᶉ…¤güGî2SÌz«*áîþ¹nǸ àon€¤˜Ù^úCa9 ‹ó^Cn¡‡BÐá‘ÑCI[„p§'Ú%«ë;m—g}ü°Õ]ÏP•·ø[ó¥ O÷:éµ÷ëT‰£“‰Œû
-Þž}®»«Yn/ß¹‚z÷뗵ĩ]ñÌå±+‡XK!€•«ú3i¥Á£ý\6my™K! ‰
-ßkzVí¶F˜•p³$Ò~ÏʧÐÄ
-ýÑ5Y’{AWÄàPtA­hÏ:^SBÔ3ñä5 ¥<+óÛu ½ ë)r§%çüÑÙžÆBdd:Ú•Ç“ i›8=Ú70îµxÅí¿)Y7-Šª_ͤÉJÓÁר¨¸µhàãa¬®¾vó‡ò™
-î8¢vC·O9¼+-Ž6Ñe%×™ ò±¬·L·>½»ð~ä¬ û¸NŽ„”IÖÊ*Ì4ŒÞ‘ÏçÀ“>ôÿ«FŸ·€õä×¼› C sÀût
-ÃÛÓJ°¡ØºE¥5Y*¡ -V¬dä³'æèhâ‚WΡ{-˜ÿt‡ŠG«îåBnYb$Ìä¹§Õ¡Yýéí.}ìÚÞɼc©íª“”.ì[»HLt´†¸O B°$üî>CÓ O/ZއªbL<.fzt pu‰;Ä¥Ì&G÷Åcå‰c+—GÁu­ð
-ƒ)¼uô¸›•Î7¼ T'ò ƒ‰–Dº
-¼»‘Då@Y¤—v-P¾qdŠï©¹è\©FŸ,ÇAUê Ž£HTE t`…ñJ&tާ·ÙQkéj¸Ì‡â‚*\Ú†¾œ!ê*z<‡A5YÝFdØF´ðÃøÙ*ô+Àùó,»¶AåxZI°°l¢T£vÒ9
-Tí‹ £x©ÚƒË“º?ª^‚ÖRjG?ÃØ¢y,´äÖ mèô
-ý63ûÚìÐü$|Ò×Zÿ$\tƒÛªœxÍ>ÛâBp@ün$ ¹±‘7?ît3]È®­ˆ1(xŽL´¿ø[«³Fn0 ¦b[+¬'>òÊ ÂXŸìßÉ3ý,"¢Ãª‚ÅN˜¹»
-Ç”^› Z>^—³›.†ÍÄ>õØ ‘ù…óq6ƒn£J6óx (³ùèݱ7x/g”î÷IÂC!HM´~Š^²atRÄØÕ“=ˆm}hi ¡‹2ž÷pÈfP…­QtÊ\À¥Úí "†^ÜU–=HO"çȸ禗ףOÁu @aÈxPo¾–,-ÀkÚk+DÙA݈³è
-‹"#s˜éµ Ø !Cƒ îb‘ 7˜HT©Ò7m0Ñ;KZ¼Á„·Á*L&_Ä`‚½¨L&_Ä`‚|Le2ù"}_8t} £;ä¹Û·ÚèÏm0‘ÎħðÂ-cèG5e×`"eœÍÔú@×òÕœ9ßà3Q¨u'Øè§öõã])ùàœ|§(Óqºs™i©×±TÂ{Í»Îg¯ÕøÃLÈÎÞ]<x+ñYð`‰ ƒ.vÓÀ½µ’Oì’V¢¢hAÅÁÕ¿h‘…÷)•
-MÛÏã*
-()%Wµr»CN´¹ â ›"ÜWYº¥¶ÕZaE<i¢Q’p£
-{éÑÅxˆÖâÍ*t;¼‰˜UI3~Ϙ8à!}r¼oåýzg]$Þ%óþÜ–é]ŽUýì©O<!ÏïO§Å¶0ì8M=œQÆÏ½“¨YN©*BŸwXNè'Vh›õ´‡
-M´t*¡…<H
-DïI8Ô¢D‰tÏÇŒÊ÷! è¸Ã#÷Ò æ|bÛ…æ|¨ ™~ÅÏ
-1¹[¹vVÎzÊSžÙèÜ+å!Ñò5">ô¢òý^–L(‰ºá6sïNÅa/9ªŽeóÔöA-b¾ÛËÛ.˜½Ý~oe?Kí¤_òÄ$‹·rrxš»…›UPyRÈ×{¬ˆ^ZoQ<³¿W79sI_
-9ØÃ_JÀi™$¢ÅîûÕ$òÚ
-êäi²ŸË€!Ó@–‘bî÷JEò‹z,C>´$´ó+)JõØhº°3•_‚|b%oZ¼å
-ˆ„ñV̶µû!¥m»“´{@ ·O>ÂA_CÈ ù"AŹ"©ð‰öøf*K|¨’”Õú|ˆ&ÉBˆ$_ ñ‡å¨Äù”©CÞ§;)o˜_~ÖÑÔHÊâ§M=&åÜQæÔ$!S¼èäü‡´ª—Jþé|O™ü°rêkI™Ê”©éK©÷"$4-Ð/ä‰AE{4Ÿ­š9¯‡U.5ØZ¶‡!!§àj"-l“¡]~›D–Æ*Q!)a¦†`;šmž’f1ãÕÆ
-‘Áˆ¥LÈ>‡nÖ¸åŸ(
-íÖ7e5èEðXK>æŽÇ«Ï¥ËΦ~<¡eüenÆ·Y!Çfã–Ñë$¦L@˜IH¨r²мzo—ƒÏÐvëëÎiq?;'ÊW?±ü'1)n\%tNq¾"Cr~";¦„œŸç¥¦ ,4ï"¼I€8Ü€îvõ@/G…$y@f5… æSˆ`â« )©Ÿ_0ÄñéßÙ¯Q‚_ÉO%Þâ@E·bèàÓˆ€&ãK 0ÞJx™ß§Ìnº•%ïdÝ­rDâ57¨C¾òÉÿ08 ¸½Ñ£ Ê>-U¹Õz<`¤¥˜TÔ'xïÁ?Ür%’)z)‡?Ñ£ñ[w°?x~|þX
-¹Ö]Ñ\¦O?:½ò Û=éþÁ¨Økß»£¥ôR4w\¨Õ’ñb·Ýët—B¼„œPìó|ÿR$•¦Äãfñ!Uy­®m6‹TcK«ŠùÙê&&.>-,¸õºáöti’éâ¿–ù4%²¹cÂHCvÎÀJ±;ÈKÁÝú¹†¢D‹Ògñ²¯º<¹j<í)f‚OWùû=æ8±“Í„àk;’:)ˆ6 cO5âÛ6Zsû7öb83uæ²ZLFÝ!6‹O·1ÇæàØÃ̱Ñq‡v/ªîÀçÊ`R3c6ГÖÄ)ßIŒÿ G°YðéÂ3¶-…à}]Žð›ÕÔûHöqErñ Ÿ^ºA¦&”âý
-² ùšö…J¯D®ˆ M<œ¦G¢[Q’1È`”1<á—_(g°µT¼h®6Å*d¿<͈¯jQùhO9ñ…†*<o„ ägÊž+…y½Wо+µ2Ý€(¢­ø
-_Æðâˆ&_ÙÌ©¾då¶ïÈ)ð¬Lh9
-kƒDÙÖbúd´½Áó±mü“ái?ôÙß×'{‰¯ØÜåiÿKíòÎ(íø_`o”wF—çËíòÎ(yÁÙJ¬1a©-=ˆ
--Ùd‚›Ç¥ŽœÛ°­ÊõÏç6Üá¯!Õ™ÂI+¦I¸òÉwÅî=ÚÆ­ƒO«Ü†n÷fCL¨—1Ö8Pæ6Œ÷ÊÚØÚß
-™ÿ Šä.raYò ‹äÄsL_„^ H®ä0_N$WÚß¾œHŽ8B¹$’çå%£ŒnŒ˜þ¾^ã›îƈéï‹2öLqcÄô÷E(î—±}c„t¾lt_Äð·\ë
-–Jj(ø•L*æ,=QÌY®%[jhbv8çSWjÉç_º8*LÂúÐLªÆS‘D
-é#IÇa°`áQ]~„í$)ŽÁgâ/õžÉ?‰F’,`j<ÅœÆ(%Öij·¹žÍF#8CŠNÅ Ql‚
-f⸃¼\1pé‰Pr-rKÒ±? p[áb¤–ØÙ8Yeâ äZÒÈ¥–&æ§¥®™Ð+ #ÑLIqX6ɪR|¦$>á§:æ&G
-+”AEcq|BG¸ê@â@7Ü’ E-@ÝL6ù„œb
-.i¬Ò3ØkÄIϤYK­ËOÄ1tà… !?M¢¥†@Qž•øL9
-Zuù·zÏ¿ÕHØKG.Yî8àŠ(xᬊ“lª9M Ñ1´ÄÚ‡ÀSÀnSÈ 8BÞ1Äôˆ1 `(Px,<ƒ-˜v#ä –<šh¯îÊ·`'ö~|4ß»¥ÇA³óŒî• ç'ÃNã ‰NœBÆÌÿåŸý¥Pˆƒz 0¾
-È—C[¦ÂÍ] ÒÅÁF]§( }šŽéý:̱0k8–â(Y!§Î·gë5o¿Wö!xƨMÅQ$€^[.˜rÞÀ8¯ü¾Ý뎺íÞ ÀF‚ž²Ñ£nóm· <âà×K¾B®VÖìä¡7xç_ ÌbÉ—ëôZÝ»\-…Ç£¯ÞºwòxøZ>ì4ɲœ-ÞCÄ´b c‰5â¹þŒ Fœ@ 4…
-¥ ¹TœÇd`Ò1$$sìþ¡¦ICìfcób7ÈA -…Sh–(¼)ÎÁ Oކú¢%N‚`v9Dïp*ij8|Š%ßr—i+†Ø èôŽØ=S¯y»½ˈG`ÿF9I€">ð ÷ÿä¦L‘[4fÈM¼Öñˆ€D-EÑw}Ø¡#ò š­}tºÀ?õ_‰ß×]†ÂTó pÓ‡þ_1å–øI¶Åœpp[~~릇¤GÍá¨;pAeX—Š+Zì~ï¹Ý=ªä—.ö\WÒ„§/%Dn–bqj‰‰'±Ã'ýø@¬%þ7¹Ä
-:(¼ƒPÇåñ!›£f–>ÉR¬ë¢ö¿ýîÛsŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSœâ§8Å)NqŠSþ?S¾ùö_uËï¾[LùúÛßðÅîO¾ýzªb8~£)/ªßo¦+¿¯ö¿Á%Ö-úp3.úíãÕtõâ”ÿ¸å â'ÓŽß«üdQýNÉ×þb¸Ùï…‹þáà§8åëi gZFm(ÎM9Ôí¿ûî×eaÓ”ðùý¬»> @@¾üÞÕ)N±,‹“aþ}#®õÅû5*Ülaí/h}¿4^錄pÑo¾û­¦‡‹:å?J™–Ê~oŒqj{à‚ÆÿÄÎ9mû¿/¼RqNåÃï~;ÉHâ”ÿez;Ø,¿ûæ7†o§ä6ßýoÚQMݯAY—^Üx¾ôj~YÛ)NùwT¾ùnù½°PÓ~=e™¶Eõû½|q.úíw¿•Š$—~­.¿ºpŠSì.úí·¿Ö-_ˆx÷Íÿã
-ß~÷?uË7ßý³nùö»2(¿™²è÷kX¾ýçéÊï«}ƒõº|ó¯úEÁ*'Ëwß}Íž‹þöë_ÿöw¿á‹ÃHòï¶|ópüë×ÿòíw_#º~÷o_÷Ûûþëo¿ù·ï¾ýúÛ¯ýëÿù¿ù—_ýö7ÿã_þùçÿ÷?ýÝÿõ?ý¿ú‰TþéþÊ?üÃ_ë—_ý•²ü’”_üÃ_þâW?úå?þ¿þÃ_BùÅ/°üýßÿXúÀ—ŸÿüGBùÅHùÓ¿ÿå À¾üì—ü³_þøð‹¿ÿÁ/þç¿úÙ_üêï~ô?ýÑßÿì‡úåïþĸüàç?ý³Ÿÿä¿þü'ÿíç?ù‹Ÿÿí¡üìo¨_~úgPþî'?€òÓ¿ýS(?ùïå§ó(?ùë?Õ”ŸýÍŸ@ùÉßü—¿ýëÿó¿ÿÕÿÍ_ýñ_ÿåAù«ÿ1_þòGåÇñŸ¡üè‡ÿéÇÿí?ÿåÿH*?ú¯ÿé/þüÿøáŸýïñçrùáŸý¿ì½÷wÕ¶ïûû÷yã¾ûîïž³3öçŒ36àŒqÀÛ8`0ÎÆœs”mIV–•sÎêœsWçêüæZ³z©ºº[˜ ¶÷á”Æwô¨.µZR‡OgXs50áÕþîzT_W]ogmOGMW[Uw{5ˆ%9WApK^íl}ÞÞ\ÑÚXÖÒXLÔPÆÔ\_ÊÔÒ ¨¹¾¤©®¸±¶¨¡æ¨©ºˆª¤¡¦¤¡º T_SAT] ª«.UW—TUWVTTä×À]µU··×öu·˜ ʀ߉£Ép8ä# ˆ'cá(ÏóÁH„FáU Åx¸„ó𺧠üÚßP²þоüÈk}ЇÂ~¸LÂy¸ †Bn·Ûl·k Ôã2‚¼nÈÇ™™8ÎUnNÇätk™. ].ÊéÔæ’ÃÕçp÷8¹^&¸
-²s] ò]×€Ë9ìr¨ÝvÈåÐdçTe•Ë¡tÚN»ÊiW;l*úÑ Ù-ꬲY†­æ!”Å4Èd5e•Å0€2úQ#‘Q?"ƒ®I«öv£àX£èTwŒ"ÕP»r° „Ôƒ½b‡û»¶ ½€Ùº¾®z÷tÔv·u¡5xÐÙZÕÑR ,…ËŽ–ç¨öæJ±Ähmª+i¬-FÕW?«¯.FÕU—"6A5•eÕ¥UÅåE…ååeeOJK=(,¼ÿ4ïÎÝ—.žýáÒ…3eåÏô&5P”¾8#|$ðŒÅ"~?xéX8‰%ã  (¾nÁ¾F¬¯û %ë¿¡àÅ JÀ 2ðAt¤ÑDRžp” …]Á›{@‘¨/™à‹Åüq±©àÎPy²*ãPÑxšb H¾x<» ?ŠýÆ”R·Ip‚â*<Oþ°ⲊÝa,æÅ[â/=nÍø«²Üž=Pâ»§2™ç³Þ»Éùd2„úÙ_ÇN“‰xñYc7Óax–#^*Ÿ>8@…Ãn±xÞ…
-‡(žw„Bv9öÛQ€ä÷¹P?ç÷¹}^§×ã òÚ<^籺8£Ñ¨Tõ(û:ºšê‹óó.þôã±ã/^:WU]îv;œÀÏp8 Ç£àB#É(Akœñ1äOÈÕ|Y¯E$•ˆA
-D£
-)ú+è÷ß™¢)ÑDh’$]cd½'ùV0ô'‚
-¹Ãaòvv4oß¶iñ¢ùyîüíô‹
-þÎ_ãо¤ûÿýR4eGG
-âÃ~Pœ,Ž£Á4“ˆøƒ<|&†ácº¦¦jÛÖ/Ǿ÷þ¤ ?_½æÛoö_½xéÉÃGùyKŸ
-žæß½{÷êåk_nÞ>uÊ̦Æ6@h(Dºñé§sz—ëx݈¬ß±âI°.ÐäI›}4¯pRŠF#¡ÁžC¿]¸`Îùs§}^}å“^îH”´¦`ÊϼJ£Yë¹'Ú½|оÔûÿ½R4õ_ˆjˆD‘¸‹„CQ8ˆ†#t-®ø05ׯ_;wö‡c?X8Á×;wݸvýу‡ŸT””ÖWÕ5Õ6ÖTTW–?/,,º}óÞñc§?š5ýç›CÁ(&êi¡3”V°{Ý3üeýwP"á G^ŸÑç3G"Y*# L àÂ¥L&£æÜÙ“ Ì>rø;³I›H’%ö|ØüÄÕL£gï)=rÕ¬éýüV”ËrãQgÑÿVÃkaüJ‰)*n£Ùõ ”TØcð/
-ÔÖ=ß´iÃøñΘ1móæÍçÏž{ü(¯0ÿYeyECMmO{w_gow[WGsgKS{qQùã‡Î_Ù¶u×{}ë>ëƒá(Á&Ø“%Gô²^¶"áíÑï·$c¾DÔ~ÆHÀE#/2ÍÌí²ÞºyeÉ' ¶n^ßÝÓçq©HÚË5‡þŠf½ÏÜÓó^-EnGßêqxí/Œ_©Dœý¬E–6u@ÐM‡Š
-‡C Ú—T*•§Nš3gÎÔ©S×­[wæÌ©GUVVÖ×Öõvô(šaµIm2ªL¥A=¤îS
-‰(âLQ¿-ìµAPχ¼
-R÷ëTýê¡^E×@O{_[sWCmxѲ’FJÑ‚ çn}ûÍ}´dÜø)6‡]”e “­_÷+ë¿´rQ4F})PÔmÑ„\FÞmІ¼¤(õY)ŠíÓ™J
-^(úøQPôüÙ›û÷
-S4à0rf¢1ŸƒQ4ÌNQq/™ó ÞŒ
-€Ôj3^¼tnÎÜ™›¿üB©€3 çãáPŒ'ÒhëTúVn¯ÿQ’•M¦Z¤°‹à¾€SòzàƒQø$ ‡‚A? T¥R<x`Æô©“&Ž_»rÅéÇóóÔU=omlêëµÍà?Ÿ>§\hó<A(
-AÁ„’/â9C!²"#Ow(
-³Vï4[¡ÄzDÄ‚†üÎ
-}&E§M[8{ÎB€»LQY/C£P”EM¤hÜëˆx¯(Q4Œ£²¸ž±”9R¢´¿ë x yê«×®üôÓåŸ\½zÙÅ9¤¡0Y^J~<c—¹_ôßB)
-‘.&’½ùŠÅbñx<èø½¾d‚ ™:|øðäɓǎ»nÍÚs?ž-.(¬©|ÞÛ‰U$½Ûj§þÓð ûBpÉ{øǃ •PŠvTh¥%«–DíléFŠVU4?«StÊ”ùóæ/s,STÖËPVŠâ”@_ÈA(tè‰õØÃœ=ìqE}žHƒ 0î¸8ò’JýHh­S´ú ´^GÈ0(Å@ï7û¾ž5kD|:ƒ6AGò&“’]êä•¡ÿ."Àá¦Òô™¥øŒ“'< á'éí„Ïã-xš¿lÉÒñãÇ/X°àÀ·ßݽ}§¤¨¸¥¡q §W§RûœN¿‹ã½þ°ðŒ(ò_D@¨#DDAÊ(ŠyQqi .!¢ê肈(ÚÜÐ}^Þ}ô äöMÒé´çë#@Ñ…/Û,STÖËP.Š’ÂxQ»‘3ª¢§1ÊÙx·çœ@ѰßCãú
-ò,[4ýš•¥%…t<™¤Gw'ÈæM4®'XD¼I(k.}íÝ¿›èÇb4½H—u—Uéb«'«‰~$O&àÙK
-P„654îÛ³üç¤ 7¬ÿâÜg ó j*ª»Z;5Ãj«Áâ¶¹
-A=P4LA
-o®hX
-R$§„¢xœŒ#EùHÐênoÙ¹cëôiSNŸ9aw˜ÙBQˆüx>ˆÛA2Š2ÉÍþlþBŠŠ—½³&VˆG¥6D
-áÉ‚&’œË}ýêµ¥Ÿ,y÷1 æÍÿþ»woß)-.iij ªWéF,(ï )ʧ(ŠmNpéØÒc8 IQ“ )jÖ˜…¤è ©+){5Y)ZYVW˜_ýð~ñk‘¢|0cíºäƒ@¦¨¬—¬LŠúÜ& ¨Ç¦A/ñ8xÎñr‚¥¥ 1;Ê@š%ºÏ(é’ì!HŒG#á@˜÷ó!ŸJ9|îì™ çlÿêËžÞ2˜4"dá öÇ–TLh¥³ôõ?zÿ~ÊIQÑþÅ9&‡¤/Bòb
-úE;×¢èB!‡«­Í-{wï™0nüŒiÓ7mØxáÜybA«ª;ÚÚµjÍ`ÁñX…Gó¦Å¢<òHT '")ŠÇn«)J“¢fLŠ’!$Ù(ÚÜÐ^[Õ\QZ[ð´êþÝgׯ>8sêê×;½ÿþ´ ·’Œ„LQY/Slß%‰5ë‡8«:è4
-rØìW/_™óÑìÞ»tÑâþ/xü¤øÙÒª4éô¤ŠD-¥8ʘ) ê1¢Gr’ñ#”¥¸ü“QÔ¤6e¥h×@w[OGs'R´¼¤(zïN!PôôÉ+»v3fò–­;eŠÊz©ï^—•¢‡>â±1ŠF=€(Š ŠŠíh&HÑ Š…é5’g‹‘­"p–„í¤›Úì&àçú5+WöiÁã<·ÝFæìe€Tö¢¥w2D% • ”Q4mò'*…PñG!Pü'(âÁm~¹ió¤ ?š9kËæ/o\¹úìi~}uMOG§Q«sÙì§ >‘œ€Ðh ,®%!]ű<ÀÓëà€Ÿ 2‡Äâ°­­ªó¤ß^Ñ£„uãÂ¥n hS}[Íó& hþ“çHÑ“'.íØ~àw&íܵO¦¨¬—*FјhPÑEývï¶`DÏ(õúŠúƒŒ¢áTŽ””´ÁðR!HÁÒ„B!ÜʼnN¥Ë®á qn{w{ÛöM›æÍœyñÜY£AGi"Æ@ŠiÒTù#ûd¶œs/_÷þ럯¬Jo ËRš—ÔèÅËÍRˆÄäÄ.&²®ŒÀóe3™™ógÏ?öƒ%/:ôݧò*JJ»ÚÚUCÈP?ç x¼A¯OÂãm'“$Gx"H=vw.Š’µŸ=jE¯’Q´½©ƒQ”Eô?¿øÕ¶ïÞ~{âÞ}h§“LQY/K¹(ðXìf•ǦñÙ´!—¼(P”ç\Y)J”“¢ÑL‘>Ãuªñ"~‚ÄÝÖ)Âó¡@Œ©Ï?>gæŒ];¿êïí#­¤´X©¢"²LÑ4Šb}D¢ìXÂOáQ¥J‘¢òEQJ(ZU^±kûW“ÇOX0g.\½x©º¢²¡¦,¨V©rX¬n»Ãërƒ …C8 ò¬¯y@¥8Š—€ø ðDÂÓl·,©½ê„êR"z (ØQÚrßÕÖØ.¡èk‘¢àE÷{H¦¨¬W# j¼nPÔk×HƒNSØk {ÎáÜ ¨Ç‹A}ÌÅýd (x£¬pO Ïãm¨x!ÆgMiÈÁ>âG0?woÞZ4Ák×475Dé} Mfî¡;‘ŸÕÈȶzØ%žCÒít»ýw~ zgÏTw•ëŸb¿hdíöEH='KuŽ4Q㸄Ï>À­ßëÃåHð-Jýãé33'O:~âÚÏVž;y:ÿa^]eUO[›¢¯Ïj4?™%±|€|°ò9›š¼b„²,(^r6R”ÌÄ3Û­z³EgQŠÒ!$ýj@(É‹v«ˆmïƒp¾¥©½±®µºª¡¬´¦0ŸäE¯]yxòÄåm[¼õÖ¸ƒ‡Ž‘dŠÊzù’¼å}œÙaQû:
-p{q^W€ª8×'ÖG:*EÓGÍKfΧÙ…i!Γ|?Ù²#x¨1Í"îµHÆðYVSU½eã¦Þ}oÞÌöíüúÞ[•Å¥m M]=z¥Òe±€ÿ„"?áù„‚à@ÜË$î 'B…Š’ÃGDÓ¡™5k Z]"UhЋŠ)ÚÚÐF(ZYÍRI#úG?¿´åËo¢G”)*ëÕHBQ¿ÇB)j »/¹Ì¼‡Dô~·#ìvA\x¼
-øé¶ÚCï%‰ñ°¼ð
-³ÚŒjΪ÷ØtA§%è²]Ž
-R¤ŠA :§3¢x '‘ÉðÖæý>`©Õhºtþ‚yóW~¶¢¬¤”ô.’=*BÂ~y>Èa^_6eßG”{ÛÊ\Êà¿p'â»b}ï£|
-H¦¹ŠþµH&6™• ?§p ®è„' ªVªŽ9úáØÞ÷½u«VŸ:~âÉÃG 5µÍíš!˜CZCwû]\x_
-BŠö´ö­i«)o*VóôQÅÝ›ùW.ÝG/úç?¾óÓ…+I™¢²^•˜Šú=«Aå¶è
-|ÂÎtèºd
-íÁ@âBQFN&Ö±üd^4*A€ÙÚd"žà# ˆ@ý
-VYDN±Òh)B(¶)‰š"øL~’uŸp
-EŠjzõV9 )ú•t÷ÏAâE:€¢MUí5¥Í@Ñ'ËïÜÈ¿tþîñÃÑ ½}ëLQY¯Xdh2ô¹lF­ˆ¢¶€Ã‰%©Q7òx¨’IQLiâBÑLÁyl‰AhÊ‹b§SœºP̯BDŸ$s…Âhqýœg°·ïì©Ó³¦Mß»woooo’ìÔ ‰¯ŠUÝþâ¶ÿL¾~‘~+Šâ]1„æ¢( Ì%ÿ^¥}eB¿gªœ'PT gŠ¢t½@Q\ðx‹ò >[ºlÜûcηo×Þ›Wn°¡vz•Ž$*m. Ïq <Î…'zN¾
-ßA$'–*Ñ‚N©übâUPÜ/ÌÖ÷ꓲ~ʲ*¿@ šà©AEéTêwîΛ3ŧ+ëjêù ° ÄôpÀð‚wŽ
- 9§)JZF!¢w¹At2Ô§(Êú^„è^hÎÏ.Œë±¯‰ 6‘K!ÉT€d¨i€Ô›€¥N»£¡®~Û–­3§Ï8}ò”ÍbÅŽG¼$[z}qÚC?’ÕÅáI1ÊQ%PÍuþE”õGÈ]¥g„? bý´Ì• ÀBKpàô‡4’Ñ xRt¢2ixˆÅáLwÇ¡ï¾:qÒäñ6±áìÉ ÔWÕõuöj†Õ6ƒùvù#ž ˆ„ð\
-‚«ˆPaãølk93…í lÒˆ˜¢b ŠY 6ŠPIRT­èWBé¦uƒ½då¶ÆŽ¦Ú–ºÊ¦ç%õŒ¢ç~¼ ]·zÇÿóí’âJ™¢²^½Ä…p@tØ3)tºü.bGI­VÈ‚±jψùü x#ûp £(“¤ï”E÷
-^ôð÷ç¢þã˜ç•urD/ëÕ #zFQ8¢—Pí¨ž¤Þä%B`ŽBQ̩Ҟ¨4‰)ŠÝ§ÈCaØííÇï‚#åNJ}å§‹‹æ/X³beEI)cg«
-Scy¤((ÚÑÜÕRßm¨jˆ¾´ æÑ½’×c^tÍÊíúÃ;5Õ2Ee½z1ŠºÌZ@¨ÇlôY->»5èrð.g&E1;šÚw¡d}(õ¢¹DALË
-øèqY_=¡°?Š•#¤( ”åBÃ.?ˆXP»•¢¨åMÃQŠ™Œœì˜,–O§(`
-0GYôVæEÅE„‚ú:ºÛz‘¢5Íu•M•Åu%ùÕŒ¢¿;»|ÉÆ¿ýåý¶Ön™¢²^½X^ÔaTs&£(õA©˜¢R±#EŠ"H¢©÷Dxã¼QzÀ–
-?˜¢#ݧ©<O‚wû97é›
-ø=NÇ@O÷þ={çÌœµg箾®îO
-ÖpÿpK-MḬ́cIè-¾û2=áè"+^3pÁI!Þ¾è’ñYtŽ›¦…‚|ŠÑ© àÌ1õj5[®^<¿pîœ1ÿxëãyóø.ïþ½ÊÒ¢ö–zÕP¿A£tÙ¬àáicRÀëôEý´"¶“ï.–éC?Êoó‚¢A@Îø˜F®Ú9ŸÍ)FQ–EŠ¢lF;)jPA΃¢`DY8F´‹,ÿìŠ6T7Õ”7TÕEóî—Þ¼þäÜ7ì?³ì“ oý}\oÏÑËzõŠF¼n›NíÐi<F£ÏlöšL¤sÐá 9]a7vyƒN.à
-Ri2)ÚÕÒ×ÒØÑPÛR[Õ--®ŠÞ¿W|óÆSFÑwÆ|08¤H$“1aQ^˜QTÞ·KÖKÙCÄÇYµ*»V EBý6+PA
-o^0¢èEŸâcd)#*^"BÙɬEŠ2ï:‚‘Ç“0ŠEÇ žO†Ãp ÇØçŽ¢ûšÊŠ­›6Κ6ýÀ7ûV[2‘d½”
-Ž9ƒ f"B‘¢hA-z€”js‚X^ bìVt©@=mM=Mõmõ5Í@Ñç• HÑ{w‹n\Â(úÞûã•*˜¢HÉë\¦¨¬—(¤(xQ ¨[¯„Â¥˜¢D6—ßN„üd¡=‚%ö¥Œ¢ì8+K™S2
-á<£¨ßfì¨= žŒœ™ ³ôQÁ"6¥™JàfT2‘ú¼io
-Á=]ýA=«"‰[ôG)¸£••$KG¯Ñcž“$?)61/Š>cRTHS²‰pzRÀíat…[ÂeñÓ‚K–ýã¯oL7aë†M—Î_À=âÛ›ÚôjÕhrXÌ^—Óç&‹â‡xJpšYag…c°QWLѬþ“Óèt¨Q(
-ðDŠ‚#SJ‡(©U
-íë7Ê
-‹Zêºút
-Í`á¬âÙeVNʺþ=—AåN‘J!”ŠfMŠ*¦(»t1E‘Ÿ(° &­/±:ð„fõ¢Ñ·5t‰)ZRTóôqPôê•G@Ñýßü0sæâÉSfM–\•#zY/O„¢|
-åñÃG&~8nì˜wÁ]Ÿ>q<?ï|Ft4µh†&÷Ó ¸Awbò§ÔLaogœYšžrQT¿³>ͦÂyPäÔÀ¡˜5jÌx‰ÕyE¿šIQÒæT߉­®¬¯(¯+!›.•BDåòÃÓ§n
-^T
-Ì„Ø_(ʧ\(YÄŽ*‡N;>uâ¤÷Þ~gŲåðYðøÁúªêîö­ReÕÁ7â‚£¤?åø\›ÇåBhÚD;§°X„IQ·…HLÑL#š•¢ˆPFQP„µ$¼
-±<Q^eÔ ëè'¤¨
-)ÚÛ>ˆmoì/ÚX×Î(ZRXûôQù½;…HÑo÷ŠÎ™³ØéâȆ±2Ee½r!EAHQ@(ˆ#ó¬H­N”ÀÒ9Y²¯Š#}q¦4—B")“Ø‚2´2Š¢$ Å3¸ì‡G¥&E(Ü¥ºÌZ}Á£Çk?[9gúÌ»7o9,VL“‚ÙÃV|ì)e+›Ä«PG)F=ŠÒÈ) ç=¤ ”ü/4 L§ÊâðKÜ\½E IŸ›«()ýtÉRš¾gç®+?] ÚÒÐ8ÐÓ«S©­F.G¡ÊèB³Fë£XPqi Û™0~Gê2»8“ by EGšêEἄŸŠÚôvUg~¢B‘¢ê!-…§‡€E{Ú†:šzÚºškÛk«š‘¢Å5O–Ñm”!E§N^0oÞ™¢²^— ¢7i•’QÔe"õ˜-H-”€S{Zû¨8À#TÒbš U¤(‚” °I “
-êEYÈ/‰úG+Zd*4´{„–K¯Õ‚ãÆÊê›¶L7áøÁÕ&³B ˆÇY¼Ð½™š§š:ãCE}¦ˆ—c¿‡)Îä%Ë‘’~NÂJÒ¤žò©ÅP8ZD9¬8~ôØ„qãǾ=fÅ’e'Ë»{¿¦¼²½±y¨gÀeq8-7< ¢Vù€|¾7»ÉÌÅ3ŠšB HÑ…ºF'A(]…ä5qŒœbÿÉ(*E¨ÎÆ(j¥²h­`AAä@c1©ÍF• ¤W4ƒZ²crŸ‡ ÷ª© „ ž6‹ö!EÉ4§Š†ŠÒú¢üê'‰½zù!RtÒ„¹ .GŠÆp‹[Ei>þÚßh²~Ç‚àÖ¬SE:-„óD”¢œÉ,€Ôl1–²à]I±e•Ü&¥4ËÊ(:bMEÍQ¬5Ú"S÷È’|ñ~lYGºâ¯öXìƒÝǾ?4uüÄ-_lìëèxÁ bLjõ½#31ÐN_a”Wåá²KRc¢/qu'þ à‡I!>žðrž¢ÂgË–,}ó¿O›2u÷ö·¯^/É/¬­x>ÐÕgÒœf;ðé' ÛÁ”fEh&EÓZ›ì^QG¨PH
-r½(Ê1Šæ,$¥È9‚P*Îk­v­ ÉIੵˆŠUh½Ä‚âÂOu¡@ÑîÖþöÆ^R£¯i««lBŠ>{ZõøAÙÝÛW.=8uâÚþ½'Ç}0kñâ.·G¦¨¬×¢dŒ·èÕÑÛµ°£N#¡¨ÛlŠ
- ¥)¥(+ÖK(ÊŽsQt¤éJWviÇ6f"4³õT2ü„k¼¸8
-Œútñ’e/¾ó6gsà<=aj_Ê…fö§|f£S³Œ«Ê9w…Ì ó …xLŠzýh}ÝVûÃÛw—²ä·þñÑôßìÞsýò•â‚ÂæÚÚ¡ž>í°,(@’³rhû~ìhb»u5ï.¯G´.~ô(*t1ù¬^ŸÙžs¤ç“ZPà§Ëà„ˬþ3B ?51¢V«ÚbQx2ÊŠUõ«‡{èBºŠB‘¢5å @Ñç%…Oªè¦KùHѽ_÷)+V¬÷AX!STÖëP"„ˆþQtfVí%Æ•ÉJQÑ#§xUÜw*nã‡öL¤PEá·ß…8E>íF3€´²¸tÅ’eÓ'N>wò4  âz Ûu».Ù<j<)¦¨d±cfÚ Õô™øOaÍ —&)û¿Ý½wêø‰¼óîúUkΞ:wÿAYQq{s‹j`À¤ÑÁ߉…¤ó FÔï$Å-<€Ÿ@Ñ
-@걉Y*ŽñG÷Ÿâó™5ý¬E(‰2ó
-t¤ täÜ0Ÿ@¹¶†¦-_lœ5eÚÌÉS¿ß·_=8Œ¡½ßÅáQA¯Èà}!š{"q,I‰÷OxžÍ„E+§ —1²C‡?à·ÀßðäþÃOæ/óæ?æLŸùÍ®Ý`A‹ò šëz»{Ô¤—Il÷9Ýt>¶w;‚Xž$3i,/Í$^ʼn»cç¼'ÕBÇÂby;‰â±‘i¤dr!Åžsd]|ŽZ¼Ð]¯µƒ›]mÙT’U™ÍJPùiP“í’ Jƒ^1"íŽxÑnDô8ʉ®ý$Õ¥Îæ~P[]wkmGãsBÑç%µeŵÑ?yX~÷fÁå ÷N½ºgç©ü}â矓m§"1Vš kêÉ
-ÐÄË{É’½„¢ƒ)*€TDQ¢_BQÌ\ß’”õG¡h&?§š‚'&WÙ1ÚTÖ§
-7|Åý!ÀP®³¹u×Öí+—.¿qéÊ™ã?
-¥v”P”A2+H³‡óZ;C(J
-óž
-~"HÁŽ3IE^C@j" ¡(––;XWB
-‚ˆŒ(P´¥¦(Š=P´´¨¦ðÉó¼û¥wn\¼pç衟vn;þæßÆoÙ²-åã‰d4NúEéˆÑHêE.STÖËÕè% ¥©ˆ¢beUœÍJZIg~7331›IQ¡n•ªOA” *)(Ú뤫¥mû¦/W-û´èI>xN •Ól5¨4%ù…«—6ùÃñGèê÷ ñ>7A¨×áð»\€V2¬Ãæ
-9QO˜wúP€P¤(^îaB~(
-FAêç<ÝíG¾?ð|ÿÝ÷fL›>yâ¤-›¿,+*îjkWô ÀßàЛüVgÄíã –BÝâÈp2E1l÷°YLÙ(*F¨ÃlGеxÄi¦ÏÌÚÈ$)*1l2A8BŠ’p>EQ@¨^ed= Ây¤(xÑ¡Ôc¿=:RÎ7ô
-TBQ· 7’s˜IDu*i^Ô™ÎFiò3w-™)Siå'KK@QÜåS¯Ð?¡bŠ‚e¢ ìm­ïn®%­Þ,¦èƒ{Å7¯?Š?ré«-Gÿü§w¿Þ³)ŠƒGdŠÊz•W—ÀˆEíz-£()¥èHi¼ÉX*QV´ŽâZGù_¤bG*¦(ÒmµÓnÒ ¹këö/V¬-Ï/ŽzC¸yeÄôÁßåµêͪÅ•ó—–.üdú¤iëWþìI¡I£Ã6'\LŠ9ODn*XGj>Áˆâ’| ä7?]¶üï{ã½1ï9Ï>óèÞý†šÚ’Âg»wì\¾xÙík·
-Á°LIeŠÒ]ꄎl=O“¢˜‚¢M}`GqáP´²¬ŽŽh®¼·èƵ<âE]Þúå! è÷‡’×3¥hª4Ï^ä2Ee½\%aFQ@¨M£FŠ:õ E¤@ÑL²3HËŸ5«™ÿ¯)Ë…Š3«à шÂesmý–/6®Zöieq)À3ˆ€ëÿ‰³ãà˜ØQšxòØ ƒJ7Ø3Pø¸àëí»æÍ˜?åÃ)ŸÌûdÛÆ-—/üÔÒP?ØÛ¥W+¬çvú¼œ‡s¹]—ÓnÐkûûzÚššo^½¶ïëÝ æÌýçßßóö;ÀÏ}{ö^»t¹ðÉÓÚçU]míƒÝ½ª!à<`y «@úùʵeÏJÉ<%€¹Ûë´»2]hVв¤¨˜¢x
-ἂ’H=Í‹Ò]êtbŠâ@Q\¸ÄÚœ:šH›(õHQ@(¨¬¤.“¢ú㘣Ç%’Q:_4,STÖ+xQ«‰DôzÕ°MG)ªÕ®Q½A
-ð-(§Á bäÌ„jV~f†ü™‰Ó\uÌ"<1œGÿ‰#š!œÇâQCUͦuëW/ÿ¬¢¨„ä6Ý~D(Âãz8
-g<b䜇EoÖ¨´í]Ïòž?xì"Äø?7mÒĹ³f.ÿdñ×_m?uüØ…ÏÀåуßïÙ¹cåòesfΘ<~Âï¾÷ö›o͘2uúÏ}wàú¥k
-î¬/ŽÜ‘bŠŠm';r
-.”R"w
-\hiÁ3¬û
-à‰½Lp{,'C@ÔògÅëW­ùbõZä=v'Ö†¼V¤p‰Ç âT)µ|t%°Ô¬1›4£Z?Ü af „äŸÜ¾~íÒùsçNŸ#zòØÑÓ'ŽƒÎŸ9}íÒÅ{7n={ü~#
-Ķ:#~n¼~Õ:0¥@T¹Œ¼Å:f˜5eØDÁ1Ê—„¥¤~Ä(:ÊâwÂK|¦°
->u âE°]ŒPAé¥éP]&EÉjDû»áûíYžô‹Öõ0Š–—Ô?«~’W~Ÿn
-Š2Þ$¤@QêË
-‹Ö~¶rÅ’eÕe`Jý.l*|bv&ãz¸D´â%\%[ÑÖP‚/›Ûi°šµF ¡vX­ìîímïìjkïlmkih®VWTÖW×4×74ÕÕ·54uµ´u·v‚ƒU (ôJ-ü¬UoFŠóœh&Yç'`ï†5ëAÀ^
-ÌXP·ÝQú¬hõòÏ6­[,õ9ÝHW¡:Cm'’.Ù&E‘® 2÷˜~ à¼Û¿‘@Õf°P¢jt
-UÙ?ˆ—о8P†5F…Ö¤ÔYÔ‡Þ‚}D¤Dn†¿Ö%nOÂ噀>$$¢²èIáŠ%ŸBtßÕÒ¡=À ?¿WLK<'=ÙŒV*»Ý0R3Yg”#T—”Ý%eheä++E‰(E ChAG(šÚ1Y%sœ¨S´³¹Ûœ@M5]Œ¢eŵ@ÑÇÊ ¢¿rùá?^?tðüçk÷‚½}÷V‚ôˆ&dŠÊzõBŠj†û¢fµÒ¢RJ(jS;
-uèMÀF¸”XÐ\ÉRq¾4«GÍzUbS3l&Ná6
-a5\Åd)PÔa²e•"râs§˜ Åóì€Ô›,Nd Ãé ²¹
-—¨¬¦4kŒŸiY6Õ¾J(JJóF `D_ðèñgK—­_³¶¶â¹ËBV£ã<,Ù“)I)x"HŒxF0¢f'Ècrø,.¸ô[Ý 8ÆNáføSHZ†ÖËJG$¥†Îá¸7VypÅ%ÆòB%ˆ’£u áË
-®Î'rÍdò3â›Ç?!<ÈÙÞØzòðñ}íÍHJéaõ©‘é)NHP×iyI¬Ä[’4’a(·z
-´ºõŸN½L¼/\(-\¯‰åÐ~óß(Ù‰¢à§ (dl3u6u[ºу¢ð¢l£êަªv…¢Å å…µ‚¢) ¹ èí ØkWBvïüáå¿¿ÛØÜ@õæE½úýEED?ÜßK…½Ûß?nï'EHe¢
-_*¬©DT'lºZÓµ3¥„b ï–™œúùž½'mª©ƒ ã.tò¢äB1](› 4y ßýQE÷Ff ñP=EÒ¼œP<ÃÉvÏ]­çîcéÝ
-;ÚÑ`ä±¼‰¼hceÛ3R´¹µ‰­Fâ­.yµr,Ï=|ôË‹€¢çáEmühH¡±h¢šêÆQRÙ”ÊÖÔ%}:)È MOBqÄS÷G¦~½ Ñzvr`i<=1 ÷¤'&öñ'Çj¬®½?y—Mðç‹¥(™r¡š^tU¬dãlAÅCÉ7ÎSeÒZJI®ç$Çð*v$aLgp §ëÌÌ0ßúMB¨Lщáñ©ÑÉÉ‘ <„îŽM•”|óù×_ïû²0»ðçñûS¼%¶¨ïa‹,ÙÇpœ€áÄ™¾Q¹C^f)[ü³wL[<„ c"°| Å5l^RÏDu%Q­Mvë
-Š¡µ¥MUEõDQCN™.­‹Öß
-Œñ¹tgÇÖo^{ecWWüÀ¢—¢^­‡EGúm‚¢ꉢ°£œ¢C
-<9EÝ‚Ô5À'Š
-_
-TÊ c ÀIñcQº˜NÞb>öþÝ驱ñØÈ¨¶ï<}ôx[CùñÁaÆÏáñ™!5™Àái ›r\Ï)z× zêC‰‡3ÂXr“9­å¤ú*™¢¢ŠË„ˆ¥ÊÅÃJ£;ß·}J#áE¡I°”ÏÐǾúéîýâ¼Â¯?ýúû/¾¯.¬œQçf‚p¤ å˜mx‚ì£
-á'‡Ù’SBl¾6ˆ ' 4’É)#ÑY)êÖ‹Ê´ï<5<¥¥è°Êð!¥“ïÛîTR,?I”— Rálrh2'=çË>ßÿÅåõ?ÝcóÙ¤Û†AËû#Óã,`K§XiŒ Š3Îr
-êÅœ#M¤/_&¢x.¶‰r’ŒP¶­'‡§¡bO[Ù¾ÕÚÝbÁ±³±E8/’¢5%Í•Åõe5®½|áÖæ÷?óõz{{@Ñ…·u%/E½ú+AQ¶8§èX/¼¨}ÌÖ?Ö70níg€-øÖ7ŒTf©&_*N:Wó'„Ã8%#J…¦F&Wњ&ÄÄ~¸mû©cÇ­í´ñ1¾+€Tê˜ Š
-–ÊWåâÝruJØÅa’ÓžÂCª/Ÿ¥1úáHSÖÑuÒ¥˜q918A׋ײTÀø½áÞ៧~Æ;d'gíþàÃ?3ÖwÞš†Q¤Ôè„}¸Ã; ˜ú1p?ÉÝŒ8º¥¨+B‰¢¢©‰„Ð>“V°g’*(ªÑjl6ãØ^ß„R^T¥¨(Ð7WÕ¢…†Ê<}¹.åEc"uDÑMïíûÇ›ûûû¼õj½Š>~ò
-¢ÊgB,ÕÒìr÷}˜°y²u$ŠÞãÝԫÉIW2LИ¿\;¡RžIÄé:!DfG¼Bu–8µ%E$|öá¾ÓûOš
-ŠöZÇúìp¡£=̈rÛ©P¢;šõÚ‡Çú†H¤§ §LQLÑ–?N%;J…ØVqƒ£êbò#
-lj@êžô‡Ôü¤»å\wËÇQœïC4N,%x
-Ø>Ú34ØÝÿÓȽ!Ë`RDâÞíŸHq1ì(,´'lÊS5ÿ9Š:µƒÂ‚r„®MQÕ‹¡2BEER”O\E»AÑÆÊ'ŠØôOZ\ Kó»qá|à»oïÙ°açøä˜—¢^­—<Qt¼wˆ 'Œè¨m 3NÞg¦¨
-Ì15;êDÑéAeÀR *BG`z‡Æ FË‘‰°Û¡Û?Øvæøi ”z~ðÑßÕ¬qf‚—`¨Š=> P”Îh(ÊÏŒNŒ ‰‡“âbŠ»]äº@±XÍXìFtd´$ŠŠâ~n,ïÁ5¬Œ>€X{TÞôÍí,!]#:9ÙIð­gˆ}?ö‰Që0€‰gÃüC·¾³Å÷ K« 
-‘5U­æ¸t)@¼VNr¾F;‡Ýu¢¥œØ”ëé”ÃÄþóŽ_ðŽ÷¶¤½í=t’!Ñ>*€I>èç ª,<· h©@¨˜àIð" *Q¹£IÄïtRl”llµàˆ±¥Ý¦68)á<Mü¤pžQ´¬-+¨E ÙÙ™¥©É†Äøì°Ðä
-ŠR³½†¢E
-Õé)q½¼ºˆ« eíîs©Â÷Ë^”(ÊòŸ6ʈEáE1`›&³¥ðº ¸Pe‹ªvˆJKj³(£h~NeŽ®4GWƺÍ
-¾“à{#êÌ©À×^ݼwï×=ñRÔ«õ(:7ÿ=(:l³Šˆ‚KEÁ1AQFW)¢×H0S UãW5•:ê1îéÿùîý¡Þ tû¦­>ç/w·uQhO1;¾P‚žÂv•®®„üM•)*JKDÑ1Û0›/)TÌ£Ôð“.xjs»'oév­5D%ò}ŽØ`j`²¹¼ñØ÷G?Ú¼;.<ë·tX…EÞÓe“Ó›‚“,Éi² ;JþS†­hª'„Êuå§LQŠâE]êj1ãYÐá|[]§ (MY’)ZUÒ$(šYByÑØèLxÑ×#AÑW^Þôå—?>™÷RÔ«õ’†¢ÃÖPtÄÚO…@0H!§mP®. –j2¥ž¢~Ù‘²'nJqþÁ$óœA¾nÙqýÒU[·•
-î­0¨Â‘
-²ÎîE=E螺FD/º’Js&§¨[fº•§àý©ó†ÜBÒõ¼x MsˆX]Þ2ˆ/tx¦®¤öÇÏøhÛÇÉq©´/’0™À XHY Q–+Eiå©I„PWŠÊMõr.¥žªKÍ&ò¨<–ï¢YŸ”%ŠÒ¬¥ÚÒ–ÊâFÊ‹òÒ£hJR(’Šž>ðÒß7~÷ÝaZåÞKQ¯ÖE èüÂ# E‡-v€Ç "ª@+ÙTÙ‘ºu§Ê½7:E¦‡Ó?Û»{€Ð-ï}
-„Þç­õ¢kTÔ’\ž8ãDBŽVÒ³ÓU¶Ÿ—ÑòÙèÒ
-²<QÔ•ŠkcSÏ5Ó‚d‰ë‰œ8’䈅F,Cp¤e¹¥?~µÿÓ>ËÍȓۓ¬=à*¨¬Ây ‡)Çø›„V‘¯ÒPT槈ßi (Ju¥Ž¦nzHm­íðDQjs*ͯ%Šf¥''æ‚¢a¡ÉׯEœ:áÿâ öï?Jz½¨Wë%áEû,FÑ ŠBÏHQOü”S¦2EñZš2±ÿ•;>Øæ{åú@¶¹´õSQ‰8 –’™”;šÈ‘º-iÎËŒ¥T€õË^”(:.Eñã’/]§ã}ÐXï¸,×3£¶1Uî±¹H•ž3“4hæq·©ãaó è
-SZ”Süù'_~ºk_~VÈ)L¦ÍØK´”óœÂdz¢¨Æ»
-j(*J¥y!b)*(JÙQ*-¢à§†¢@hMI3(
-#ê–¢×®†Ÿ<î÷Âóï:tʱ¼â¥¨Wë¦V£ìí5w1/Úcîéc.ÔÚ”Ù{û{a~†ˆŸC½v2¨2H58Õ0“‘°dªtÂ6tŒê6 n÷&¦MíFÿk7?ذéúåk}–ÞûS÷dÃ)7&yjUrÛÎäz±x[b¦ìZ ²,ëHo"²r1X ={ N"´‚·2rÆ=«ÂWñdA]g¹®>' 'EVœ¶Ú­yYù{wïƒ#-É/Ä9ëÀPß[BÙ6ÔgÁov˜Ö\¢U@qÄxÀ6ÈÅ[¦^ú~ëð@ψ<AIÓ *JKò¼$Å…võО lÀKó<œK{LíöÎæž¶†n¨µ¾³¥®ÇÖzcSMG}ekm9«Î³ÒRiCiQmQ~¯.•e¦•¤$ÇEBˆþ”ï {ëè‘3p¢++Ž%ÇìúßP^ý ŠStx¨ê± Y{†¬½2EqO [eŠz©[–2ÇØ;xw`l¼gpÌÊÚPÙS|¦§¥Ó„~ëÆÍ7¯úÚ­}S0œ’{Ôô/Éh}–¦&W*Sõ]^«DôC<ËÚÏ3™´œ&«ž{¤¥§•ŽˆŸkHA´*
-Ì<E¨îÚÉ)R”Ñ5äRÊg‚‡#ýccƒºT=´´ |t`´!ÁR ”Öÿ$ºâzŒ{º{û{ð§õêŤ$ÚÁSƒM1GIîUfÇ·÷ˆ¥ìÙÎt|A{ ´³ÙÄ–®<ìëh²› (Ú\ÛŽcK]Wcu{]E Q”…ó|åBC%µÜEc#óÂB2Ñ?v=yâ(º¼¼äXž[ÿÊ«A­Ì!¢ÆMdE-VPtÈj¶ô"¾î³Ù‰¢àÚúˆ¢2He¢ºÍˆÂ|žÃ;XJë™ –ï3Û®œ»„ú]õź79ƒ˜z°w@S
-ß²qÛ_ïo¬iEq×K)¢'_J=.pKQy¥Mk¨\Ž ¢ 3\(Ûœ®ÍDS>AQŽP8ÒW/ª¡(yQ·½s+=(úü_ÿqÕÇßKQ¯ÖQ‚¢6Sç Õ¼6EáEaS!·,u[o¢¾}`j¨opfbÚØÚyêȉ·DÞ
-ÅKØ Pûн‰i|­QɈŠÒ¹¦ªî¦*ô4=#`‰¢£vî'ùÞCœ–OŸ‹¤™ï:›I.å³±´o“óìx!¹t®i."ipJ©Q›±GViâINˆ¶¶vµvÜÚðgOœo¨nZÁLòŸT]‚àíÖ~Q]¢\¨ÛUïH5;€)q=¯.áKCdD»ZÌð¢PG“å¥%FѦš6È•¢eÅu®‰È½˜|ãzäýçAÑ׃(¢÷V—¼ZñUŽ ¸ë°˜Ì–sLQ˜“!Ë€ è€¹,õà –Rßþ`ï
-¢Ãs@QDôß}{
-
- óRÔ«u–cnb|¸§»=(Ê#z+¡ …Q$QÏNšl‚¢‚¥3é2 Î3ò‰ðM5 ¿Û¿sóö¨à¨~KÿÄàM2¥õɯRÔ?Ü×/kÄ> ²4—y’|±æhW>顊Ó^`Ml…9!sRvŒšµ•ä¶O÷
-‚¢°£äKû­Ã¢Tn
-E%šÝIv”ÒžbŽ'Þ“Úìá?©4“í¬¯ ä$R³(Ây ü„ªÚ(¢'„ª—àEËò²KU/š©GDåRØ·ßœþós¯…‡Åñ~ÑEÇò“õ¿›¼úדce…EÑÛ»Ô÷À"
-í–Þ>³ G:OGØHŠñÉ”K[€tzlª¡ªîÄ¡c[7nމÆÍ¿‚¢-ûL3¤˜íU¦í©Ùvþ&/*ÞÁ“Au;•‰]Æ)ªÂp|í¹œš}ßÖšÿþ4xjò¢®ÀtݰCˆŸÔôDE)¨'–3GúÇÎ=p|ó{[ná¤p¤\ð±,ºÇ˜ÒžT`’É)/
-6:í
-“‰°½²¸üû/¿Ý½íذ(»Ù
-La0Ìr­ƒ#=lbÔ€u
-ó)Öe{húšÄbw2<)¨?¿Ó¬O˜OQT²Ä
-ô”%„ª¥%ÆÏÊâFZФÄP“ŸS‰ˆ^—QÄ–hŽËEƒE¿ùú(“ Ê(ê­.yµ¢êÒØè€–¢¬
-ÜggÍÛ ¤L’¼(QT€”ÔkêÁ,²v™ÁU Ê K¿ûâ›O>ü88à6À„ötõ
-Bù¬%„óDQ¾&^m£h•JQ(‘zùbØ×_üÓ_NLÌEU-.{)êÕzhen~áyQDôý&3!”(Êda Ul'¹SgŠ1(ÊÊñ¶~\952QQTŠ@>9&ïƒ@ž0Šâ!(:ÄÚ]åqªã]èÏråÚ×S·¹ë•n÷¾”®¡½³?”ßU«èSò³škij25yÚ³_~¨ˆ÷)ÑfÇ@¢(;ò†ÒÊ’êï¿úqç–]‰1ɼ@ßÏ(3¥T]"«I8ÕÔ’ÄVÈ
-vÑ OÀPƒ_·³8HåØ\ O•«.T¬"ÄOö¹9oëEWÃùn†PNª(¤ɺÍïmýbïW…¹E<ô`u(JP^Î…Šr¼±ÕBá¼H‡ª!¼‰âwXP™¢ 5Ú)(ÚXÙ9ѱÄ}qAe~NM®¾NŸY/š’ª‹‹Ó…‡fùûe¢Ÿî;öoÿþ·lC!§¨wQ¯ÖI+sË+óS“#ð¢So—a»bGý½ÆA~?Úú¬Ìy²i2j:þ“ªK4 ¤hž.ç‹O>Û¹y».%CäHÙõ qÊB_«<q^ø×ÓüqW¹µ‹²?Ô8@Odx’ëŠÄôí)tuž:$]`WòÉZ©S8]Xç*1ÃÝmäÎÉ’-îÔ'Þ$o$‹Z˜Ø‚óífïæNkLxܶ|ýÙ7•%U´J .
-EW¼5z¯ÖC+s è½™ SGK¯±“(ŠˆEm]v™¢ÌFr/Jdšz²Ó³>ùðãÝÛ>LO&
-JøR2±ŠºÒ‰}9µ7àŸ è*¦ø[yÂò³@ï·òü7½•à¤+?ÝEè®vô)¥ª(ÇköEZÝ`ޝüÉ LìmáEAQs§oÛÚÐ~ãÊÍMïn>yätCUË m´­¡ ×S,/¦s"ÌÇÑØŒˆÞ":BL5Ê6÷”Ô-Je›Îó¹óu g½0¢ri *È­2dW‚¢)‚¢¡Á¬Óé|Øî]ßÿõ¯o´¶uy)êÕzŠW—îß›¤½­³‹QNÑž.[Og·7 ¨©×d±±T›…jôvkß°}(3%cïîOvnÙ¡KͤYNÔ5Úƒ¨í2STOWDHÑ3ÅIñГ4¾î)¤r¡ñêû<[8¬µv¿QnÈ&þ-’ᔿÍWôDH×oI{»Z’¦gžÕ‰ºl–«µŸŒ}æv 8cn7›;­ø–Ú;Î?·á/½¨òUJìlu&^WâIQ»¹£ÏØÚ#J8¥à·†Ê¥ç;ZjÚEÅò# (çg=ª&EhßÏRƒBQ}F™ ht”.äNzÀÍô çB?ÜùíóÏ¿ÑÙev¬,;–ç½k:yµ>Z™Ãß(Jý¢ ¨­Ó¬¥¨ÙB áXýñÞ'{vFÎÞÝŸîÞþQFr¦š¹Ÿé%cÃ|Ž©῵“½›J—ÏBQ·~Õõäý­ü§ù©wørsLê?_~O BÅÅl>»‡ÕÞÓõk9wujÞA^¹ÎÜÖƒ_®¥Ý™ZNÁRöíí͈ Ë‹*~¡½¯Ÿ±ÍÄ6Nê°Ð2¡ü í̈¶ö
-v÷{ÔJ:nd 5Øw·»»L€*€™™¢Ûúþ¶]ÛvçgÒ
-~ÊIQp’·6u3~Öw¶Ô·A´³’º¬=‹èëªÛj«Zk*[ª+š…-+j
-‘ù$ŠŠõš¸Ì®¥mAhM{QPAѲâ:P´¤ -È¥uHE³ÒÊÓ’ S’rEo^‹?{2}ãµý#l­û•ÇzßM^ýk
-{Ð/~êjÃ]{^ÔŒˆž²— _¯¹GQšé™—òÁ†Í hzR&oÕ6Q,©D”*<å“ÊSNòD9Íe¹R×íI%áV.¼ß3áN†ªË'Bü”'ÉWÊ']q-#Tó%äÕ;*ÝzÎÕ ]ºÀ•™šõ“YO{'‘)5³†y Q´§³¯£±“~§=vmûhó{[SâÓ¨ë‰V`†„ÿ$/JíLjw(Æ-u ¡u­DQ¾ s«LѪò&HPT„󂢬å>µŒ(š¯=s"póû{ßykËÈðÛ”[‚u¿¡¼úþðVV?úµ£½ÕÜe¤&K›‘Õ:-”á4¶uÓ⽺Ô,ÜJ;6„âöÇ-F;ä²)Õm&¼„öÙ!­MQs»em`>UŠzÂìÚÌøÒ0ÐÍÇ3W5ôótf êj¾ åz—5èHk,,Oë!“h©d cåU”‰¢¤‚¢àø)ioê¤ß&ø îݽ/3%‹*P]-涆.ª+QG(±”@Jeéк†ÐºVÕ…2Š*+8UµÂ…
-„Šˆ^´8¿Ž‚zP4;³œ(Šˆ
-Ï ˆþÔ1ÿMïíÙðζёIô ¡ÞˆÞ«õÐÂ(ê˜}ÜÝeìhn‡çD ol1Ò 0¶6ठMŠMþpë®íìÌHÖáÆÇSMÝp&êÆŽ&ÚaGÜÅò²ç ªí²Ì¦6EÎç-®t•!ùTŠÒõØëŽ]®¥‡®
-ç5…•)š›UÎJK)¥2Eƒo¥^¿о÷Îî÷ÞÝ>6:EyÑÅ%ïú¢^­ƒ@QÇÊÒÂÂBoooc}SWk§ ®²µ»³ÍÔÞbìj7c€Û?)6eÛ¦í;·|¨KÕÓf|ˆn `60&Šºj•«­&UÝ ¨[ºÅ)9Xù) EÅùµŒ®âA‚“®`ÔP×£ßfÏZHÔôE9aqÒ´^WÙ}Xýl?Xªž»õŸ„Bôrñó§‡êœLìÙÕU”•‘Ï‚ú@TJâJN\ z·7ÃïDnzwóg{¾ â»…á”cyiÑne{ò@hm ‡§rBeŠB‰¢@h‘¡†"z>ƒ¾,+½4#¹DP42,ýNPÊ ŸXPtÃÛ»>x×Äøôвcˆ×‹zµZt,,,-.-;¦¦¦êÛÛÛ›:ºš»Ú[@Q“Ùh3vX¿ïܲëýw>HŽKED‰»¾¢µ¾·Xw›­µÞØÙìDQqûó“V.îvZº¹ŒPW³"õ¤"™®®Œu=‰1áQœ§±'2»R‹À%È)z’œµpe)à)$(Š1ü<$ÎK€uÿž‚–b Rl 'ÆâÇ®îsÔ èÑ‘DNq“‹íV—©g±|}Æøêô*üºÈÃ”Þ Ùøö¦Ï?ù"/Ë`5öˆ¢”»PšéÙÍ[CyE ­i&~r„6×U´°]ê¤ê¼[в+ÝR^=qäæ»o}¸}ë'Ów¢ê’—¢^­‹Vçæ—WV=zÒÔÐÜRૹ½¡£±¡Ãlìëî´¥%ëÅä%ftµ²»î‚î,Ú€ ä{ãvk@ªŽÝSTO’äW=JÃX/ðHÏj`ëFÎès…á„ôÄR·3eŠz’x·îv³SbY*QS0P6ù„GË”7ßtkGÙ›HFTóåDhzJÚu®‹m¦¶ÆŽËç|ÞyãÝo¿ø®ØPbiï#óIÍ¢bާ+E ¡‚¢lAfÕˆž hq~-Eô
-U•µ@TšW’¢Eµ¼@_Má<ŸA_’™^Ä ôlúg|¬."4ãvPúÕKŒ¢ÿxcËž¿øùgPÔá­Ñ{µ^â]ZZX^^š¹;]YRQ]VSW^_WÝ’–¬ß±õã­ìJˆJÁ­S[ÞØVßÞRÛ
-µÖvˆi)8Ò½C,e-‚bÜÐN ¸†¶2o]¡
-¶C"
-L»v9öØ¡o¼öÁ'{¾|ðàW¢¨×‹zµ.Zt,,-/ÎÏÏ..Î//9Ú[Ë
-˱ôĬÝÛ>yçõ±á‰¸º[,MU­¬XPÓ‚;‚»À˜‰Mëc7Ýe$j´f‚¸ïÚ›êÛ„èÌÚjiìЈ¶‘I`‡ KL'¦V'±Ô($ÓÕ•ŠB (þùrÚV¡VÃ^Ù3+RdY2Í4ˆÓ<µê¥2[ñ+-BòÔ!AEד¾º:O±x¤ÎÕÅú6ú°Ã¿_˜óbCé¡޼þÊ[gN^(/©îl³Ô×´6Öµ7Öu¶4v·ÔuEY_ݺ֗71y¦(iIa åE))Ê7P.ÏÊ(ËH-NM6pŠfE¯_‰E_uÓ§{¿þõ×G^ŠzµŽš_|âXYXX|­,/Ýœ.*(MŠMùxǧo½º!üv4 ·ÉV#/m
-#J…¥p^©Ñ;S4<$óV@(zôàõW_ÞøÅçß?~<륨Wë)ô‹—WØ$&8Ò•å•úÚ¦[w¿ñÒÛ×o#4«)©G VWÖHb¾¢ªQPTQUKmU#TWÝÑX=Ó‹"„‡$ºãêÛ!ÁRPÔHYÆ@Y¨T'µó£Xò¢­¾]˜áÖx§vj9bg¤´­@Äj—'~i©aQªV‰FÊj ¬›&Ç(¼Ÿ&vËw¸FÓ
-åÖD(û6ØçH·ŒD·„Ô€ñiØôHQˆ_8Ò+;;wß§_¾úÊ›×®úÕ <iêª¯í¨­nk¬5”²ËUвВªÖBhIë´/®SÂù‚jò¢‚¢Ù™¥ºôR>‰Þ E_þû†o¿987·ÀŠKÞ ^­“–Wf:–Ÿ°õps+++SÇŽœ<üÃñŠ¢šš²†ÚòƲ‚*
-Ç@Ôšòºê²ZˆžZÝè¡¢ª©l‚äqmU3$³wå»Ý¸_u+¸YV¶¨n# ¶«]]ÇRM´Šd¬È¸*ç]J`Nå0µvFØÔ,’©¨Ñ¸†Á²kr=ŽÞ\ÝPC.Ò­þ[d`jDü§¢ž®üÔÐR~(ïh,Îx¢(\(åºÅlÄ/¥¡¶¥ÐPºï“/ß|mÃuŸ
-³Ò‹3ÓJÒ’‹S’ØR$q1:P4È?ýÚåØÃû¯þý…w~üáèâ¢ÃKQ¯ÖU¡Å¥G`)·£óKKË=V{R|F®¾¨(¿¢ÐP^Y\[URW]Z®Bå…Õ8âdeq=©ª¤Ö” ÞˆÆ5•-‚¥dA%SÚF¢ÛƵU­êÝ礆Z…¢MU­2H‰¢„6M¦ºM©e𠃜dXM5¨+ iÊašÅ„•7¯iï”ò«¦×Ť­ZõMœL²Zƒ“Ÿrh¬Öøgö³÷q «Ãt¡¢–¢jWR—±ù›$
-çiþÙQV|¯m¯,k3S“²>ÞõÙ{ïl òÅ(>õÔß/=*hsºf^š§í’›5e3è9EyR´Š(
-­R41_¦¨ÏÅèC?ú¼øüÛœÀ_¬º¾èºßM^ýkêáÂÒ/Ë+aGŸà¯q~~qÙ±b·àÖÈHÍ)È++.¨,+®#HË k¡Š¢:ÐÊâFvG”­. a ²”ùÒªò=„
-ر´¸®¸°ƒ2ÄhˆÔJÊÕ¶juõžz"*
-l•BÑUF+i¨P1hèÀÒŠfv,o…+A¿v
-ò‰ÎÊ0äç–êÒó³Ò‹ô%Ù™¥†ìjêHÉÍ*ËÍ).È//.ªKIÄÒ’âê²ÒZXY–Úâšò’ZðS Q¥•I#À’ð°¶´¡¾¼I©pU°¶™†²ÆÆò¦Æ²–úr Uqªð<õ•Í¢(LéŒ(s¸ÕËXÉŒ·5
-Ó ÉxU9‰ÃäÖÈÍ
-·,œ­À¦|bk•EàWí®2åÇä}7dŸ©A¢ØdÓíIê’ÔÁ7˜ãÿÒêf¦š6Í>êª: æz>øb„Ç|°qÇ[olˆ‰Š¯¯mj¨mÁï—]F“•?›D^´ª¤‰S´U’¢ø‹ªÊÓ—S8OÍ¢n)zñløÁ®€¢'Oœ£Iô ¨w­{¯ÖEóË0ž Ô5ªRtzB”´´´ôóÏ¿4Ô·„Þ‰¼îz':>Z—«OI0¤%¥'g¥•çèøÚe™†œì"}VAVfanvi~^–­E…•P¡¡n>–p
-HRAp
-©Œ­'„*ë¤ñXÊͲôlqˆZSR޵°@+ëÅRëÊ4m>¦E!±?…{U²ö-¼¼”F,%¨ÊhU,q•VŠÝU_"œ³HA„Êy ù¡Ì^W·¬®†Ô¢B»C–ʽvOÒ0Óå‚NRc5©]iõ”þurÏ’øxB8P¢¶’%H›ŒÍ ·ÃßzcãÆw7GGÄ7Ö!ŽàÛ*ñ,:~)Ê%ψ²¤hq#w¡Õp¡")*S43½¥¹K qY1QDÑ gÂöw鿞{íì™K‚¢KïšN^­ƒ7Kby¤V¬Ÿ›87ÿˆ¥›Œª“3eÅUp×|‚|.]¿zçæ0?ßðÛA±‘á©Ñ‘iq1éI Yi)†ÌôB½®ÿY™%ÙY¥9ú2ܸGhZJ¢¶ÜªÂüšâÂ:[C%¯¡Œl)î¬â: ÄÃòÂZò-ßl·¾ªˆi•®|ûH>‡&Âíˆq]Eõ(ÖVÔ»•´%:‘¹®Lí/o’qÊçàh%h㖮γÈYµ…X$Nj^å‘öªÙÖ€ÐÓp•HèIô±¢ªC#±)ýëÄÇÒ°Ä󜭈èÒ*üœ+Û©¤XWÝæïòÚËoïܶ'6*A}Iaþ½øžÙ^ó<³ŠÐ"µMT¥(/ÐWh(ššTœ˜«¡èß\xîO¯\¼pÕKQ¯ÖYŽ)QTIÑ;æOæ—Séüü<[3W.°¿©±ÍWœ˜qûV„ïÀ×|®øž;sã¹›7®ƒ«wnÅßJŒŽÈLŠÏÃß?îe™i%ºôÒìŒJHŸ^¡Ï¬ÌÊ`Ç\}•!§DÍÏKkÀÕü¼*Cne¡º´¸¡¬¤G¶´­ßKª,n„*ø€¥¤nˆàI#$X!Œ·i¹J'+%“ÀO–+
-OQ‡˜«ä…LN ŽðèŠP˜*eµ{’Ó¿«rU¢ a,aGAÅšŠ6<D€_[ÕzíJàK/üc׎½©I™50ùÕ¬ÿ ?ŠŠRYà2ŽÐFuMf¥ÇI´9Qu 1Ž[ŠÞLEDÿÝWçþô‡—ð·§nâè½Z/9D,O¥iñg .T—`JñËâãCß±È?ýWž<y299i³ÙÚÚZJJjÒÓs##“#.]
-8uêêéS×Ïžñ½pÎÏçò­€›ÑaÁ)1‘º¤øüŒä]jYjÂ4 µL—^®ãuX¬^W
-‹cºÔj
-~²O7 §øì;{úê«/½µç£O3Óõõøêõø†yꦎ2Š–*%ÊgÐW‘ÍͪÔP4>V™z'(úí—gAQ|ŽÓB÷^Šzµî’
--ðeÃÙäP X7þ"u5/.=YX|Ìö¼[^NqÄSüYàuéñ“¹¿<œ˜œ1[úªk †²¤$]XXÂÍÁÏûž:ásòø•Ó'¯=}#Ð?2äN|ltfb|vBœÂm’‘V˜’˜ãªÏ,ÏÖUde°Ù9Y•yÙÕ€jnv¢ÒŽ<ù9<9€[{܆¬m  ²¬ ª¬°8-+¨¡¦,Ñš…#N’¨e‹ž‚J‹ª!µ!võ¼ìråþXÊ'€¥„S°” 
- ñ™2]^ÔœÀ-Y-=õ›$ÚÆ¤“T†s:)÷•‰63!v !«ÊZ¹œð(D1¸x(.GDô%Ài;Þ¤ÈP[WÓUSÕ~äðéŸùë/¿Ñed7ÖµÒ?™6W?I´ž (Íçb¥¥H@QÞæ”‘r;-À7…(úŸ|9(0DÝtÉKQ¯ÖI+s$ú#T¥<K,]a{1<VÔ¸iq aþìÂÂ(
-ºÎÍ?Z\~Lá-±ùPȱœëüÂòO??œœ˜ž´˜ûjkZôYq1é!ÁÑW}üOž¸pòø¥Ëýü|Ãü"üo†‡§E†eÆEç$Äæ%Æ’
-àZ3RKÓS `K ÜVÌ©êʲ3KÙv™å,'[•ãš[^h(/6”B…9åPq^ei~u‰¡
-G“4 %ZR…‹çêe~ºe)k×)V@*pJñ>ÄO1®¬h€ª*! *Êëé! \EWº
-ŽN&¡ïS^V±ŽˆÒZ è=½ey‹‹Z+]L&µŸA”Æ$É8%ÀÂ[žåÅ msa^ ÃieÞ³¨°òø±ÓÏÿõ…¯¿ü®Ð
-xÒÿt«"Šfg2 Š’Î@Hr;0=w*äó½ÇAÑ”äÌã°Ü”Ã;wÉ«ÿ¶"¨âHäT‹þ,5ªža—Á*p±9§"äÇCÒÒÊ#.~RKÅ+ƒ*þ_Z\™Ÿs<~4?}÷'[OSc[EyMfFvtTüMß  ç¯8vñðÁóÇ]>}üúå‹~7"Cn§D…ëâ¢sb"õ±QÙð3‰ñ:ì+ìnFZazjAj²7¬.­„¸J¢ÔkVf1ì+ÙTš™®ÒYñ¬¸&Ÿ•Àª{™§å,•E˜%¬‰± "çå±{œº³ˆÔéÎD¹ÕË
-ëEçƒ8éVLñ&òâµ8‚ô†ÔVµ¦%ç|¶÷»¿>÷ÚñÃq¦ª¬?%)–§‰Ÿ ¤¼S´á<DMŠÏ‹Ö#ôˆKEo^O:{2xÏ®ƒÿõÜk¹9…¼[Tó!î•Wÿ¥˜O‰¢‹ê˜]@U¦íCKOpƱ2»´òdÁñ+ÓòŽÓ'ª”¶Uˆù þ…ÿ¼çŠVV=y<=}oltª×6ÜP×™›]BD\¹xôðÅCû/œ9é{åâí«Wn_ó¹s+(n6"<>:2%&*ö&1>›uÑÄd'Åç¥Á¦¦Ð€Å
-5¨ #Êö­KÎg¥%NQü¾EÏŸýôã#Ïÿõ†¼b¶¢Óò¼—¢^ý7™ÆE—5ÆÅ9ƒ:çx"´°2?¿<7ç`'g—Ï:Î-?]éYv˜]™›_žÅàÉâ£'sgçŸ,,±üêüâÜÜÂ,·‘–•R¬¿<x<>6ÝÞf.*¨NIÎ
- ‰¹é{ûÒÅ«çÏ]>wöòÙ3W ‹ç}¯^¹uãZð[qa!IÑ‘éq1:(1^C qzÂ,ˆ
-®²zV*%]õ@k Ͼ‹l
-æ‹ïMå6ë¥< óXñ ýà½Ýûóë§ûàåp¤9ºR|ÿô“áÑ2Ú=93µÑAZ’5‹Jý­€¤ë>ñgNÜADÿ·¿¼ /Ê:™WYRÔKQ¯þ;Kùv’â' ³œ¢³ çüò4ç`SøØt(Ò<
-¯r@¸òÉâcÎXö’Ež2¥/„÷y2÷pvþ™[xì`V‹ìýç.,>fí.ŽÙå•yÖźÌì«B×¥¥_~ùehhÈh4UW׿dçÇǥܾás9àÔ‰Ëp­G?~ôÒÙÓ×/]ð¿~õέÀè°Ä¨Èô訌øØ¬¤„°Gên¥‡¢a€ìkfz"P˜Œ¥¼«,™±´¨»€-MÛ¢<¡¬‚\0³FˆZg¹ªÜ
-à’¯ç™µü¤Ô¢é]Cr¹ÖFç50=óâ}pBño<S|Ûj#{624yë¦=¯¼øî…3¾øry™¯”(ª~01ŠB hJb~bœ¼hxhr _ÂÕ˱'ŽîÞñã‹Ï¿]YQǺîñÂâšõ¿¼òꟖs$NRòœ<í¿
-ψKÆÏßß7îÊÅèÓÇooÞøÅk¯¼oµØñ«œ_|⥨W^ý^ZÍÙÒì
-8qÜçÇÎþøÃù£G®ž=tÍ'òæØ
-–B‚«2<Á[&7±• °,ö¬;r
-)­_¹•„M…¥|Á.8Ïì¬ÒKü_}ù½—ÿþîk!@¨0¢ø IM*‚â
-ð1ŠFEfÁêß
-Ð]»’pòØo¾:ÿççÞ8uú‚ce™ÅõRÔ+¯~/¹A(«õ3ç¹@üTXº8???«.a­´°é®V2£Ä,—CíérÌÎÏMNݳ÷7·t•%&¥…ûøž?óСSž>zøÜ©>l=–S7¯]
-½íŸ’z;#ìNfx°>*,762?:œ)6*;.:Š1$Ŧ%—¦&–&Å¥$''$'R`VSr¡Œ4Cfz~zj t€§Ž÷0ئ–‘‰å¢”cíV K”½˜›Õ9¥gI0±äf…茺rˆVr,/Gv½®”Öé‚s.0Ô@—.üåϯ¿úòÆ
- ÀºÎ> “²`AeQYcXZ!âxálÀóyû…¿¾sùÂ]z9(ŠO ü»E#sÂB2ý“ün$_¾sæÔí¯¾8õ¿þí…€€Ðe^_â‘‚2 yýÿÀ¼òê¼Ü{Q¶õ2Ñ’@ʵ´ ÍTåü‚ºv{‡äí÷‡#/ö+Ó]q™ÔxÃm­²
-¾•|+•W²tÑaÅQa†ÈP}L¤Žü*Œ_ld~| ,k>'*ó®lý–8J½‘’â ‰ºÀ,W¾L]Jiâ²”ä"_X\Jئ«È%¿Ê °‚e|ÝŒÔRPýðŸçþøÿöþ…³·ñYr'ãæ¸ÐKçcO»óíW—^|~Ó+/oî2šð3aõ>†Ð¹¹ÅGË´/ÃúÿyåÕÿxý_¤¨;¢þFŠ.©‹]S6U,|½¤¬ÈV ‹ð*˜´ ÇÇgfî÷õŽ´4 y¥q±© çùsW9èÀé¯>?
-øá™“΄\:á듨÷»žt; P½Äè’ãºÂFGdÇDæˆ&ò«<ïšKfÉ»ª‰ác SWù Q h*ÏЕtÂK(ó€cL¤>"4ãà—ÿðï¯ý×¾}äÀµ@ÿ$ÿ›I7®&;|ûØá >ÿ·ÿïùŒŒBøÿGOóüó­lC êõþëòÊ+¯þi©8ý«µˆ§È‹jÖÁæŒe=WjñkV))¹ÜʸÒsss÷ïßèîî®,oAÈr Š8uÜﻯÎ}ñé‰/>=…Ø:q–5ÐçR˜ïµh߸@¿„[þÉÁAijó•ŽËÊ[t´Ì ‰²Æ!6Õ;[ 5%™µc‘UÊ«Zä¿“Å%á…±QY`itDfDhà®ÿò³Ïýá­?ýÇ›Ÿ||øê娳§"N Ù²é‡?üÇëçÏßüßì½gt\Ç•¨ûÿ¾ñϻޯ·–þx­{gîñŒíǶ¬ÄœÄ R b¦(1SŒ"ÅœsÎ9$
-ð§h V)HZå‘0n)¥ ämZ$1ìt½½½M]Z\wÿîÓÓ'¯ìþáØæïö|³tãâEkÌ_,^´qÙ7[׮ٽ黃;¶ŸÞµóÜÞÝ÷ï½ Øwíàþë‡Ü8rèúñ#71j=~˜– ¹{úèý3'ž>þ
-Át9}=*m]}Kγ‚ë×ï9rfëÖ½«Vm^¶lýܯV@– j]¾lËêU?¬]½wãúƒ À=»H¼zp{¯G@¤z÷øÁ»G<@Ž|xüÐ#¸<²ïÁ¡=÷öüpcßî[»w^ý~ë¹MN¬[s𛯷Ϝñí{ïŒû÷ßtøðY)
-^Å’× Ài,²¯‡$¹Ý^‹ÅÖ«Ñ·¶tUVÔ•W>Ï/Éz’[PXÚÙ¥¶ÚcËP0(N)vÙfðY$‡óx ‹b†N Ä#1”jŠzWP¨¢Ny¯«EŠ»`‹A/Ãòa9Ùê
-Äô³Æ,¬=Kˆžalå
-ÀâFÛ1‹úeybT<ø-‡Ãùï@êÌ=%ñ•
-ÝÐ*
-BR;`Ó/±1 8÷Z¥¨<'…á(®BByb'+).ÆDÚÇbS`ƒþðr8œ_<gôiÆKÓY”ÖA%È–Ì.ÅÒó©—»§Ò ¦ ÜV…–­âm þŒ-äáÓX+̳6,(a A±ÆIY—Åg—8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡ÃyÃüú×,šùþôeÓ5áã_ýúO~? ¾5ý›e³–þjø¯Æþê?ßú_ÿû­ ãõëiô›Î]0ë±/Þ5gî"ù¶¿ž·û×·&|Gÿòþ¬s¿œ5ê£wßš0¾þ¾ñøï_ßú¿ÿú›ß¼õ‡ûÏ·¦¼õ»ßÿæ­ûýàê _¥» ¹"v»ØÿÿðÖoéÍÈÍÿÁmÈýù5½3äùã[¿ýÝ~û›ßþjÂ'ÿcÐ^‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8‡Ãáp8玈) E_ Áˆ€¼èD‚/EÚûŸîO~U¿7ür ÖùÃä)NIêÇ-=©Ï“þuõr·çp~¾¼‹¾Ä¼ìýOk•4?òª~ïKÚéÕÿÕØlP,
-¿ôãÀáp‚/ûÆyYQ§ ç^ò®¾¢OPÔŸ†WöÁô’Ïà<署ôb€—2è/TçGyu1ÌO‹tÖzí¿7ilöÊÎÿŠžß×ýºJqO¨EÃÑ@¸E9?^ö]6hb|éñÀWtÿ&ãœ/{þÁz]Å™Sye4,RçgÁ˃½FBa!íw_Ò6átÿ^ö^½ôïMÃ+²ô«»?¯ûÙ|½16‡ó",¤dP:àïõ¿$/{žWõ{î¼v‹F¢‹Kƒñ þû‚ÃyqÒX4ñ§ä5½yCa’'%á¨;%‘¨- ÂK’ú÷¦%â~9ëüižß—&,¦F¡Êd¢Ñ ‚ ý€p‘r~²„£d‚C z#Ñ y¹F¥`4 EàŒ„¥h$ úý«àµ»×­wÚ´kŸÝÒ˰™5€ÙÜ“K·Åhî2Z:LÖNò¥¹ 0 C';@ôúc#¥Á`jà
-’Ý/8DÉ‚žhÂ
-‚!Ç^ âóÙ
-Í´vR¼s±ž<*Æö/Þ‰»}ܤRj˜uò/
-)^´l
-u€˜-Šþwî
-‹†C@:K f“ôPÄHwûtUþ,eAÊ©8ÿ‹XTŠéî›ò&_?ðwé]Jy{òáéf) !¿R"†É·äCVLþnÿR,&d|Uľ…
-•BäÓ6"’/êó„Ü.ÅdìS÷uww´4ÖT”f?μxáÜœÙ3,˜WYY†¿ß ø|Aòâç¯Ïç
-¾`DJÞÎaAíÇîüzÑ4uGФ©VÀK^ó ßÅ4ä#ÈK`b!VÚ 7v{„™A KH¿Té;K¹†…d¾±óÄ®I²4ñ'*ÔC„LT¢R’ΊñÁ˜¬8:æJIz‹Æã 8ˆ—Æ¢/t†Ò®éMû÷çai2̱ʇ1áK|`•‘ Reç'¢Èë{Ü’Ëá0™ŒÚ>­ª«»½¥º¼ìÈý}øþ?üÃÿøýï[RR (…!úiÎ3zÎ`!‚.E´ JQ´^<·ÿ³Oþó»µsuºî@À /l:ÓK"ä÷;
-Ié3Dù6J…²w=§ËÅâOÕ¯n ábãŠÑ”gÊjíEÑÀø{öä
- öØñó"]ú"~Ãó'üå5)Ñ”·WÜ u¸›.Ö8îUü± 8)7’#ßc]ˆHIMˆä‹‚XÔa1zUåEÏ¿[·öOøúÇÿõÿÏ?þó?ÿŸÏ?ŸØÒÜ¡‹­DÑ…â„>‡ó†#’¯…<’dó»õc[æí3ã‡üyùÒ…êî¶(¼Í~Èž‚ ¼H„,” …ƒðÚ‡«è¿P"Yx¦ü(¡' '+Zö'™?JEü¬Í“æqø{l¾ê>ƒþÂHâ¥×éÇ"jI"¶$)?š ’IÔ•„¨ä‰ø}d4€ä㛓rЀèw»D¯O«Öœ=sjÒ¸±ÿñÛ{ïí¿L;fÉ‚ù‹Íûð£w§1¹£³^†$ ¤€¼ Ãþ¤q` Ç ûÑãü’—´[pú%g `÷yôÑ ÍcéɺiÆ´I˾YT]UJçðÉÜh„Lƒƒ3ÃzŒ×Àkˆfÿ>‹R†“-ÊDš~²é Zôï°ßg‹Æ ¡Q2è"ë=É·üa¿7â‘¢ýHb”BAÉëqÕVVmÛ´ù“?|çÏ?zÔúÕ«öíúaï;wïÚ¹aú±cF}õÕlFW#Õ‘Ä%Ný㱃ÿ
-À‡>âlT'ü©ßeIúdÊqóòJÒØò•YŽ[ôo‚µ™R&û(7âÏ ß/¸éiPŒŠnÉ É¸<°
-hÔ=gOŸ™5}Ƈï¾7nÌØÕ+V=xè̉“—νráü¥‹ç?º}ë¶áÇ:tR!Qir ÆHûEÊjBûáü‚‘‚ÎHÔ#HV°h Dª©Á!I.Qp××U®]³bÆô)÷ïÝòy´Ò/
-
-Ø‚=èwF~0h$ SH~š
->¯#7;sÑüÙ3g}QRZÀÊóØx~Úó¿¸7âë<ÿæó¼F‹¾À¾Hÿãð µh-
-á")N¦þ„tþYÎÓeË–6dòäI7®¿råRFFFaaaUUUSSKGGWG[»¦K …ö´«ZÚ+Ëjór‹²2Ÿ]»zûÔÉóK¿^1lØgd5“èaëéØìÏè9¯
-\Ç…/68ˆV·S %[Hr
-‚ƒ4!ëÐcCXA¿à'å÷ÉÛÜ\½výªYsfܼ}Íé¶)?úñlAEý3¶|L¾'òRî_Š.~a¤ý€{™Û‡iãz¼ Âë!‚ø^N’$
-ÔFG5]½Ì¢5• ¥EÕy¹…™Ï®^¾wâØÅó—¼÷ÁûÕµU‘h8Åø·(çÕÁ^]²ßho[·Íà´è$ŸUòÚE ,JŠê!ù
-ŠØl„ÕsB^©Ëiyôðά™ÓV¯ZVYQ¥›5Ü_ôÀYÇ‹B¹EÙ¤}~c£¸ BP›ÍrëÖ9³gŒ;òËSÁ¥3<Ï«(/íhoíÓôêµ:§Õ`¡Ø,Z XÚ×E2ú®Öîö¦ŽÆºÖêŠF´èÃO®]¹ìèÙ ë·üù/=uæ¤b”^±‚ƒ[”óêHiQP(òÙ›ße ŠI¤k™é (RÚß'ï-1H5à‹F¤’âüo–Ì_4vVæ}»Ã þc#&Líñ%úJ’Vp~–$­Ãk0…!/R`®ªªØºeÓ¸±£??fýê•W.œÏ}šUQRÜÒPßÛÓmÒimF«ÃlwY³Ó¦·YuV‹Ö
-é<(TÓAÑŽæÎÖ†¶úšæÊ²ú’ªü¼Ò‡ž^¿v,ºmëîO‡|¶výº„8²H¹E9¯å 8‰E-}@Ðk|N³èsŠ‚G’))Àƒ:@
-R$?Ñ))s"ã]Á€? ùj*·l\÷Åä‰gÏœ°Ydû0lgGë XïÜä9÷äÎ?<Fý ’îéë¿A\ßBE3Cš¼ÀëÁhÒ^¿veÖô/Æ9oö¬ƒ{÷ܸr¹ ÷Y}uUGKkŸJm3™«ÝhuY«Çir¢B“¶[×Û¡S·kºZÑ¢í1‹Öäæ”?¸—}íê]Èè7müaøðq‹—,•+‘;ìoË€-¦û‘äü`=l±WxHaQÁ©zÍ’Û I½(¸A¤‚ߤsôèR25@uJgB~¿g
-¡€¦»ëäÑ#S§LÜ»gggG ÛŠQžx
-K)`Je¿ÍØšÁÁ¬8Sh\Wí„·i€— zê«7}·nÔðaGÞ´víå³gŸe=­()mmlÒª5Bð)¸ý€Q‹ê0:lz»¹ÏbP!‹ªÚÔ-΋ÖU7U”ÖTççVe>z~ëFÆ™S×·m90jÔÔY³ç‘Î rØ&Í ¹E9¯ÖÇý±ê Þk¯Ë¬öY!5C8
- nÁï
-H‚(ø@’¡ „[†ƒ–‚N#Q£@zéе'N«åúå “&Ž]õí²ŠÊú&’£P!
-&ý÷¤˜9•p‹þdaþLÜ› ¬hJ˜£‡+õ†ÞKÏ~9cê'¼»pΜ“‡gÞ¾S–—ßPU£jï6öê!øôØ\~§WtûáÀkqº »Öjî3ƒBu=úÞÎ>]·QÓ®em©o«­j,/©-z^•›]õð~îÍëN¿²sû±Ñ£¾;îsÏgÑp”[”óJHÈÁØzœ]²ô9MˆEE—!à±XÔç”|n$ yÇ?ëUp“#ÜGŒH/ö¥×ãxôðî’ÅóçΛ•ùø†»~Ñ¿.!" Eä—iXÂð ‡ýQâ Êql:ícûˆØBUIZ3‰øÄôúœð‚‘Û|ü•%kV¯=jø¨‘ÃÖ­ZqéÜÙœÌÌò¶ÚMg§©O‘§×îà‡\¢Ïáq[vƒ¢P¸dá`Q@ÕÚÛÓªêhîjmhkªm©©l(+®XôYv9µhæé“×¾ßvh„™C†Ž4[-ŠQP&R‰l•8Ø,çgM:‹†h\
-uÕ‚]':ô`QÁmE‹BRŸÒ¢X>Lô(ù*«J7oÙ0yÊ„cÇaY~€ŒŽ°O~€ìAö÷üñ;h þ£ÄAÒYTMƒ~Œ6ÉV]T›p3R’ô“aœ ÐÕÙzúÔ±©S&ùôù_Í<tpïûw
-rŸÕ–—wµ´™Ôe‚B­`NP(àw@Ôa²Ùô6œTÂ\žŒˆvöi:zÁ¢Ý-=4'­®¨‹B,
-}pïXôÔ‰«Û·‹ÿlŒÍaçå¼¶¨Çª‹úmZ°hÐm xl’×)z]dŽIôB^HŠE™HQª¼ƒ´Jª¹¥~÷ž_LŸ¼k÷÷}:5mi$u§d[°?(`\Ê-úÓD9Á'÷²£Ûcáú#¶ [sèä#|IFuœö¬'™_/Yôé'}>~ÜæMë!£–•YVTØ\[«îè2kõ.‹Ímµû.Èâ•…ÐjÑZ 7õš±F,ªn×ô´hºš1om¬i®*¯+-ª.̯ÌyZ½q-2ú­›÷7cä¨ñ.›[”ó:PZ4L³0¥E}VÓ [4ä±2‹ü©-ªÌâú|Bì
-
-ˆÔdÖ=wrÒçãV~ûMwW\t>, !‘tH£¥Sñ[¹ þ£ÄI…¼©™X p_Ð)y=ˆþ |’J‚ßï…öôtíÚµsì˜QŸ ºxþ¼£dÜ¿SR𼺼¬£¥Ù¢3@ü þôØ…ú^'à³>°¨Ëâ óò¤@Ô¨‘+í±ÆIiцê&fÑì¬ÒûwsТ[6í;vúØqŸ{ý>nQÎë Á¢¬ÍrˆZÔoÓ»ŒÁ¦• øÜ`Ñ à ‰ibð)€B!æD—¯°ÙM2îÍ_0gÖÌ/òó²i¿"RJqcÍø­0ÿQâÈ(J+厠„’$æ²"# O·à¢‘Ûí|øðþ¢E ÀŸÓ¦NÞô݆‹gÏä>Í*/.övu4}6ƒ JâO—@BPÁkó«Çmqc,JÓy3XÊÆE;›º0£G‹BFŸlÑÑ£§Mœ4 äÎ-Êy `Q1à#Õ«Ñ¢a·5à²Ü°hPaQ Gdq=s)‹He‹Òújœ_À¿à.+-\<ÿ«¯æ|yñây»Ó"$²¼”üxÒ.!¼^ô'AÌB¤Š‰ŒÞôÿ …BápØïõyÝžh„4™ílïØ³gψ#>þøã%‹Ÿ<~âiæã¢üçÍõ8‹Ôç0YhüéyJ.E—(8EˆB,
-
-ÅpT.¥
-%«–­¯jD‹äU<}R¢´èÈ‘S&O™Á1·(çuҢإÔ'X‰EýÖ>‹º,’Ó"¹ìA+&R? áŽK Ó ˜0SߟÚcé}K¯¤TW[ó¶­ß?2¾^­&B[òF£ »Ôñ•¡?Èp¸©4}f©>Ãä …|>Ÿ$ˆa2¼ñ¸Ü™2fÏœ5tèЩS§îü~ÇÍë7²³žV••·55÷ö¨<6›×îÝ^ÉCü ($òO@V¨U P‘2‹â¸¨rj .!£ïhìlk쀌,ZYV }ž[½w'ûúURé´ù»½`Ñi_Ì‚°™[”ó:HgQ2q
-
-[›[ºÛ;ÌzƒÓjóYA·/ä!‚H}vQRXÔ*¸-d±’ÝhM-™Ð¢8(гKí hѺʰhiQ5³èµ+Ñ¢#FLž>c1'·(ç5“°C"©µë,†¯­çèƒnÄ¢’ËòºÃ>OÐo?HEÈà¸,†*t7dEš¯t,¼ûÀ™‹1óþÙÓ§,]4?'û1mOA:éÑÝɃ>²yÍëÉ (7 eÅ¥ƒþÐýÔ ‹ÁøIº”»¬&þ –z²™#Å„ÃÑ<{PO8O |6 M¸žIÈâmë•K—¿˜:mÈ'ŸÎœñåž]»ï\¿ŸWWYÛÑÜ®UõÙŒVÝ-Ð!Pˆ?^QÅ©y¿Òy/‚K>i™¨g—ô*±h§^Ó®U·õu5wmíMµÍõU Ñ—V=Ï-}’YýÕË÷޽6lâÜy‹iFïYT¹ŽžWÝs^Ì¢¬©2XÔ¤ëòX{»,òØnÄ¢X4A¤döX”Œ›á?åw#RýaÉïuXs³2W,]<cú”ëׯúü®h4è=þ O dEF‹BoóØžæÜ¢©žÍøEµq léª[ºg\âö±˜?ˆ“ïø SåÂc|~²›\0„a'
-ªëÕ*“Öè0ÛA¡>§,**@…’©yø–“¥àO¸Ä°¨Mo£K–ÌF<;O–Ï·‘t¾³© HiQˆEig¼Ë`Ñ¡C',X¸”fôÜ¢œ×KJ‹µn‹,òX1…"a¯D
-I=XT¢"…7WPJ)š3Á¢x £EÅ€ß4ÖVmX¿zÌè‘G´X l¡(d~¢èÇí ™EÜ¢©ŸÍ—´¨rÙ;+abñHlC$È(h$ê´;._¼4ëË™¼÷þÔÉS~رóæõ9O³«**!íëéíA)¢G€(´R>fQ,s‚K/È–Ã՛ѢµAm'óJÝÍê”ÍVò8£ðîí§W.ÝE‹~òÉØÅK–“nQÎk&Ù¢‡,ê2«1 ¸¬¢Óp;åp”Z”ŠT`á(iŠì>iJ—ì`Ib8|’èOOwçÉǦN›´vÝ·MÍu¤1i@…ƒÜKRq@+Þ¥ƒÿèýôHkQÅþÅi:‡Ä^äÁOÈ)è?Z¹Ä(yø²º²j˦ÍÆ ;zÌŠeËOŸ<EBЂºšZJmÖqE<ÎÂcð)Q‹â¤<&òhT0'*-ŠÇ“ -JE 8(Jš¤²heYmqAe^Nq棂Û7Ÿ\¾xçØ‘‹ßmØýÑG£—-_MF$¸E9¯¶ïRB,jèëpšT~›,*9-‚ÃJÆEÝ."R7àõ2‹öçõÔ¥Êý ~ìK´(Ä¢aÒ(߇ Ó<^¨Òb6^¿qyö¬é æÏÉÏËÆ–&|ÓÁÕT"üð§G¬.oXLÖØ†”m
-Ò5_JP(>q’$ùà§C €Õl¹xþ¤ ?ùèãYÓgìÙùC惇%àϪꮶv}o™E¢!¥r”93!©ÇŒÍIÚP—âòOfQ½JŸÒ¢­ m5Mu•õhÑÜì"°è­Á¢G_ظ~×ûïXµz·(絢ܽ.¥E}Ö¾€ËÌ,t9A¤`Q)XTŽ&‹T%8¼FÆÙBd«ì%i;©ßýf‹ü¹tÑü…s¿Ê|pßa1“>{I"å±hñ• Á‘&(”Y4®ó'S¨ò£,
-ñ' "D›ß®XùÙ°áÆ_µòÛ+.>y”QZXÔTW¯ÓôÚÍ—ÍŠhNPhÐ')ç’ЮÊ\žòt[àO€ô!1Z-:“QcÀ¢òì|©·ïjRB;qáR#X´¢´¦èyX4ãás´èáƒçÖ¯ÝùÞ{Ÿmظ•[”óZa )6
-óòËŠŠ!Õt÷X&‡Åê¶;
-…ƒä“yVW‰<¨R™Å'ˆü òD‘ÂÍ`1k±½êäÙ%´(dô`QGiÉ}CMym‚E¯\º‹…Xtû÷»¹E9o†Õ¸z°¨Û¢‘úmzÉm–ÜVŸÓp:€ ËI}ÈãÂ^ÒPƒÞ蛸ÇÀëñ6QÎñ•£¦4e‡d€ü‚Ÿ›W¯MŸ2õ›Å‹*+Ê‚´‹>¶†&=÷0:U˜ŸÍ‘‘mõ°J< ‰Û龺ýw^…½STȧJ÷G±_Ô¿v ë"cN6ÔÙ_D!·ã’?û@·^·—#Á·Ô=ªãG1jÔÐá‹çÎ?yøhÆÝû%ùM55]--&üÉBP’ËûÈ«˜¶¨É­T(ÅK§ÙŽ%=ñ SŸÁØ«¨Ei’V(”Œ‹6öX´¶ÒùªŠÚò’ꂲg9E3È¸è¥ w<¿fõηß²k÷~²ƒ·(çõ“ð–÷8 V£Êcí‘R‹’ŒžYTrÊáh‚E•`Pú£A A@$Æ"[Ñëƒ7fVF报_Ïürúµ«—Ú)ÈãqÁÛ,*>Üã^9®+KU9Ö§äg‘hÑøVó =çã'Ùån!I‘'ùþdËŽà¡Æae­E4ϲ¢‚ÂUËW|òÁ‡“ÇMغá»[W®å?Í©)«hkhêëî¶‚BÑŸð|B8PÖ2)ëB•¡òŒ’ÕC Ã¡É5ht
-— áŠNx²P¡ªîžý{÷}úñ'}ðá’ 8øðî½²¢âúÊZuG‡tÝáµ;ÃðÀ{| R$Á¢?žÈCðS(ißdq¹¬n»Éá0“­ç­›Eo5ô1…t^nqߪ‹hѦê&Ù¢E5E¹¹OŠÝË»y5ã¹Û‹þáßß;súB”[”ó¦`(XÔ벚´=c/ˆÔg5ølfŸÍâs8À¢jQɃQ‡,R HÈq,µ'¥+î“ÁŠ}\ ÿä¤ÒO$±¾µÉû:‚Ä‹c‡3çIÖâù ¾œ>ãöÍ[pK\ÖäóyäœiÓõ„˜qÿhÒš‚W"À„ÚË#ágåPYA(V†D¬Ë»¥û‹rbl¡§Dc~1¬˜æÃG’E¤ýÈ#ELæìÇOæÏ]ðáûM7qû¦m7._/Ì-¨.«j©oÖöô:L6ȵqžÝïtƒ9cÂô`\ŠR…cøn‚6ûýIñØÝn›´ €?hQ¸…šu°¨V¥ïëÑõvkÕ½=íêî6ÒÑÜÕÖH,ZW^_]RSYXS”Sž›Y ½qåÑùÓ7î;ýýoß¹xáyIp‹rÞ,`QŸÛfÒªe‹ZL^« ,êw:™EE·›"Ç!q¥ö@âBQfN«ØG²XTðÉ3~¯…µÑH8""z} Òúêš5+¿2qÒé“§´Z-Y B@Kl,Š8=€ED$»èåíŒ}ýÛΠ<n£)‡Ê
-s*‰³¥B¡X¦¤(Š“ýIÖ}ÂD»‘§Çå&U²¿œº«ûØ¡ÃÂülÔâ…KN9qÿÖ½‚gϪë;[: ¹…’­å\ðĉ!xšHé†ç_
-Å¢Xé¦Q(ޝBF%}…$ q½NW{sˉ#GdzeË–æææ(Ù©7è÷“¸Vž¬JªöW–ý'úz)^•EñTL¡é,Êó„?¿¤uer½gl:O¶¨lΘEézÙ¢¸"ÞçrgedÎ5{ÈGOû|òÖ[®^¸ÂšÚõõô’J³Ós\}AáI§1§ _
-¥þt3‹"hQ½Æ
-(«vý¤³`4Ø‚’Xx“á¿àñFѶ¦æí›·Œ6|ØÇC—Ì_|êèÉ÷–</n®kRwôXt&,ƒ÷9½¢Ãt !ˆk‘~ªË7@XÂΗyZe‘*CPŒBT¨NMÒy–ÔS‹ª:[H
-´Ô“½BªËj+KªË « Ÿ•?{\|ÿvÎk™§N\Û·ûÌò¥›û¯o?z˜Åg—8o°¨à†`@±(XÔc2ø,f°¨à°I;ZÂQ
-L¥]…YF‹Jò~|igg’&n^
-êÉ$N©Ó;NOr]®ìU:O¥þ?V
-‚HC¢€ò$ePôá¥×ˆ.›ýÖµë‚~üþ“ÆNܳc÷½›wsgW•’¦vzµÖ®3{-NÁî‘ûŠ8¼hÑþÖ".‘l–”´)¹œ)RJ&åÝhNej3Ú´((@…±Œ^¶(írßoÑÒç•9e`Ñwž¡Ewï<¹tñÆßýÛ_33²IãnQΛ,*zl&mM¯…‚H›Õg³ EIÉ(dôv@7 £I}Ì¢¬îEÎîåâüÔ`^uM¬±I8%øp@ššúÈ|¸Ôf±–•”®Yµzܘ±G1MXñˆ—d R·'LkÈáGRFqx¥Rę RMwý‹òGÈ©âG仹~[¦ ÀbKˆÀé')$£5ð¤DhGeRð
-Ã5­u»w|?jøg#†[ùͲ‡?~YZPÒR߬îT™µFô§d÷\~€¤ðNX€/Q¡òÆñ©Ör&ƒå ¬ÓˆÒ¢Ê-
-˜´fªÐ„AQUWk(”nZ×Þ\GöP®)¯«(®*ɯxž]Ê,zòøU°è’…ëÿýwïf?Íçå¼y”…tDê·Z’-ê·Ù½vŽ’¹ZyÔ³öŒHÌãÀÙëƒ%Ì¢Œ„ºS–݃°å€×€Ná I‡ÍÞXß°oÏÞφ ß²isOW7›}Æ\ý£!LÔ)²x¦JIô+Í©D„F©»„¹uÙŸ/6’šn°—ý AI3§ yôÈ#‰Z úÛׯÍùò‹O?ü`ò„ñ?lÿþþí;ÏžW—Uµ6´Am3X<fGÀá ¹ ì# ]Š
-J7øÀ¾ô ÜéCÞòÃæJgQ2JdQ”§Õ`C˜ES*Q´(Æ¢`QˆEÑ¢Ñ_»òbÑ=?œ‹þáßßž_Â3zΛ3zfQ@™Ñ'XÃÑy’ù&7…9€EqL•ÖDÅ¡´(VŸ¢åf´¶¿ ©ÓjëíQ]8svú”©‹æÍÏËÎÁfìl
-Ú 6
-õ[ûñY<qæL²hb"ŸÊ¢ÊD>Ù¢ÊbQˆE•"mªmt¾²¤cÑ‹îÝuzÞœoÁ¢¥%U<£ç¼y”±((-ê6IRo#"ÅAQ¥E1¯—ËG]´(.qÂQPºbT&ìò„èABøš`T¥ßЇ´_DbRƒ¥XMê°XËŠŠ×~»jüè1'Ž5ôiqDN „‹:3å ^äÓ[4õJØþ(L)% {ܪ1¯ï¤èõ±u`ÑÚÊŠÍÖüþŸ 
-!èéãGž>~PYZÔÒP«éî‚»Éùµß%HÞ Î¡EA¡l,T²{‚Z<HÌ¢^Ä;†B̙̜ì˜,–·(h
-2GŒ}&‹*-Š
-ZêÛkšÑ¢åE•%ùùOK²3
-™Ewí81gæòÿúÏjª¹E9o6.jÕ©œz-³($õ~+©Ò¢(ReDŠE‘‚Ec+î ø%rºƒô€-!”0•Eû«Ocx==ðcÞíu:HÝ”Ïë²YÛš·oÞ2iÜøÍ6¶44FD2a 燃Plijòˆ;NH½•7`w 9&²â5i\)çûþ=!iŸEûh±nZüiäSŒvȇ^Mãų§¦}>éý¿¾ýÅä){vî¸ûV~NVmUiOG«VÝm7› †§…I>·Í õÒy ;Iòn÷à4½`õ"^³@‹ú­ U¸ÆÃèÿÒâô˜É0‹²áP´(bÖY
-õéêE""Z1ñŠ^Ï壪:;®^¼0}Êä…s¿ª()&]ôc㨴fRv&“s‚H™c¥Ørþ@RAB˜Ê–k±sÆÝŒ:þ¨¨W}ñ
-(ª/E‡“ؼè\ªïÕ<yôpþœÙS'M|pç.Ö™£Nô
-ÙCÄã4iz,X…zÍ&°(ŠÞ¼ˆb,
-þT£K™QñÊ®L©P´(‹]û•¢ˆñŲãˆ(F% .áëü!"…ì¾(?oõŠåãGÙ¹m»ÍdŽF¢¬–¤ŽÕX2U*µ™<¤œOlJ»&X”i“™“cd®ì2ÇP~‰±(\F}ÀÃð\À¢Áܲª¤dÕòeïþåÏcF|¶fåŠ+ÎgÜ¿WZ˜ßÖTß§ê1ôi­‹'Þ“èF¶ç›^Û΃ZTþMê)rÊ,ÊH°(ÇN­
-±(XÔÑ×
-…K¥E f»×B@²ÔEŠ(ãRfQvœÒ¥,R•G
-dòSnò-Mg÷¥3ç>;þíÿúãô)“ìÙ}÷æüœgõÕ5­-:Úa1ÇFAã%ϧ3‘²éuøAWlz(Á¢L›J…*Y: EíZú“¢‚zMJ‹b
-ô´ÓbÑ&ðg(´µ¾-
-é<X´èyZôqF>Xôò¥hÑiÓæòég*u/Z”¾°¹E9o²Ã‚×……B:Ï,ê5[äpÔ'OfÎd‘*]úRE±(ƒÒd">¸™‰ú€¬Ð‡äÜHk :Ýîîö޳'OM;nÅÒoÊŠŠ‰B!¹§«Ÿ ©g³HÊý&Ü1”M,xŽÇ9Éà'Õ&Ž‹b‚Ç8(*S‘²ƒ°{’Ïábv…[ÂåÓG™ófÎþëÿ4rȰÕËVœ;u÷ˆ¯­¨éS©M:½ÕhpÛmY>Lg‚N“gØ™EáØn”q+-š2þ$æÔÙZ+2€EAžhQˆH•…Ò&$Ý4í…ѳX”Y4óQXôÒÅû`Ñßùüó9C†ŽÔôjIÛ*ì·ÍV‹r^`шߣ´(5èШD
-=X” ÜÈ´™ ReŽÏ¾d:UŠTµ2‹²9©“Ô>¶ž”é”\éöDÀ«¨Éï²X|.·NÓ{ûú…sç-øj.À5˜Ý³æüXر% Ñ'¥?^GJë””³Kp̆IÙìUZ”Þò2˜“Ô„£=mgŽ?räGï¼3Öœƒ»÷^9w!/+»±º¶³¹Õª7Û ‹Îà±9@¿n«GDSÚ3ú”_‚Et/¥EÝF›?Jí?u6†£
-Çö^«Ò¢èOBP½Æˆ—8;ò…¦ŒE!£¯)kPZ4;«èуg`Ñ‹îE·o;4nÜŒ#ÇéôÆtå=çõA,*úÀ¢Æž.{o/³¨S¯scI=¼›Ì6·É
-—@‚Q¡p¥Ò–hQ¼%»}ÂlTŠ)ûô„\‰«JÙjÓˆÛ
-`\J«1q«_»ÙÒÞܲõ»M#†Ûõý­ZÊ«DÙ"J¥E“ëê“kŸÒùvà9zå1»H™Î£ñîECauW÷={‡:äã÷?€èúèÁ÷ïÁgD]E•º£K¯Öâ~š>»ÏïðÓFLÞXƒúþ.LÊ팓§æ•Oé,š¿³>.þŒ¥ó
-E0FÅ:Éã¡­õIM)º´³µíȃcGŽúvÙòêò
-ìÝ OЊ،T¹TŠU¤¬bb¥ å¬ý=¨YÁ§7V<OK=ÉÒô'<>Q!@Š—œ¼¿÷Çët=ËzºxþAáOØúÝÆk—.æ<ɪ­¬jkhÒ©4vÙi°†\‚`õ²Åï ÁîñÛÒ6\JˆEq™’×ìÆMåˆEMNP¨‹Úg‘ª AãüÙgl}k¯ÙÜg¶h­VYÔ¤5zz!ÖVTKkDI[{¼ìj%SK-uÔ7×vVW4V–ÉÅ¢yeùÏÊrž”<zwózæå‹÷º¼}ËáÑ#§Mœ8ÝjsÐÒÐ
-%‹X¥`w{ÇáýF ÿìÃwß›7{|<¸s·¤ °±¶NÓÝcêÓA܈ Ž¢Þ@Ð)¦Û<.Bã:ÚÙäÅò
-8I'“,R“ ‘]3',Å/•™¾r¤4‚•€"e(CP¦VfQ$A¤x .;ÅæQ±NÑDJ>d©vƒ¦/óÞƒÅsçO3îæÕkV£ ‡I!ØÃR|¬)e+›”«Pû ©hF=
-:fó†Μ…´ª¬¼­©¹·GeÒéq96UÆ(4e¶>@ªœZÂr&Ìß1
-µìN½rù‹öÕ+Òù&XÔÜgL½fð'ŠUuh¨<»± À,ÚTÓQWÑTSÖPY\[\P‰}šYôðî3ºò=´è¨S'OžÉ-Ê, £×kºênfQ»žXÔe0Ê"5ZY§–¸òQe‚¯ThB‰i²TÑ¢(Rh“H&–Ô3‹²”?!ëïw¬b‘©\Ðî’K.Ý&+
-àåêÍX?ÕØ5$èq1n'ï#Ìp“åHQ¯WÂ_J†I}"Iäc‹¡°µHwg×}û‡ úñ»ïÏ›9ûðÞý÷oÞ.Êͯ-¯ìhj³­6£ÕÏ‚¢TÞg…8ß:ÈLŸÅ3‘*ŠB‰H1
-u€u6¢Pº
-É­w2s*ãOfÑD…öš™EM£Æ!(@ÔF½Ê ëÑ}]Zu»†ì˜ÜÒMH:›U4
-m‡¤ž‹¶ EI7§¼²¼œÒ¬ŒÂ‡wI,zñü]´ègÃ>Ÿ6mZ4„[Ü*,J'èÃþFãü‚äÖÐÛµöj 'P‹:õY¤ À\Ê’÷I*cQfÑ„ÛĹ”޲2‹ö‡¦Šâ(65Ð"SGÿ’|å~,YG»â¯v-íuûØ=jèðUß,o©k
-ÅôÔ¢Må…ÕÅyåE¹J‹ž?{ûð‹Û6úøÃ1³g/rº<XÊ-ÊyÃDCZÔ¤Q1‹Z Z‡NŸ`Q©²ä)å|SÊo1Ç2mbÊŽÙ˜jr%ÂRSeõ)Nú,å‡+1ÅáGÒEÊ㇚µz›ÁŽújÆÌÙ_̸}õºÓlÅ~zr×¾XšÜØŸú™µNMÑ®*mßÒƒÎ#OÄã ¨Û‹¡¯Ãd¹{ýæœ/g¾÷ö_'Œ»mÓæËç/<Í|\Y\ÜÑÔ¢éì†$é49!ÑöÚ¼XÑÄvë kÞín—b]üÀC  Ò2T®b"xLnÁ1gÍ' AÁŸv­ .SÆŸéJü©6ZI j2©ŒÆ"O…2…¢E{ZUM]…¶5t%XŠ-Ê-‹>Ï.ü°€nº”ÝòÝÞ9oÞR¤Ü¢œÁ ôCFÿR@¤É³ö +»&¥EYFbDâ—ʺSe¿2µg‰**7¸ ü.Ô)úÜhÑ@¤ùOsæÍœ=føˆ“‡‚Ê ¯³±]×±ê’õ£Æ+•MXlÅœ×C5¾g þQ8ç…K“º[Û¿ß´eÔÐ៼÷ÁÒ‹N9zÿögYOk+«zÚÚôê^¸Ÿ8‘$8>!õÚˆEq ð'XÔçô¢HÉÊMêUåqJ…²Xówˆ9åFvZ;‹6•%áh,þdMHá1øL°¨YmL´h·QÛeèëÔÃ%ÐÛ¡ëÏŠFP¨hkèIŒEK›ªKË
-ª˜E³<º-gô`ÑÍ÷¿ÿ —{}‚2£‹r‹r^;ѰhÖi´ªN£º,jíÕ€H´(Agré͈Ôe$(]ªÌñŽ?•×'Ïé§œ„J y|
-ÐÈë{q8Ñ'XÔªíE‹Ê"UX”ð2eÂL÷­„iý,šìO9RÉWÙ1†©¬Nn ú
-{ÐX®¾²zãêµóg͹rÀ¥+¿þ¦(7CD²ö‡n¦%8Àm£I‚OÎé'[‘͉äÁ<?›…›¹,6ì"gó¹H¯9ÁãÅîÊ1
-(-'Òôe"M)Õä+•Î`6* £•½O™9á®bøÇFÀ‡ÕµV­}=¾ÿ¤ªîè:òôôϧ|1iòk7¬z#ní²ÙÁ>—Óm·a’î! «áTd¥`uË[YÝ~ ˜Ü øÌNTü°ŸÓjƒh–žÄ òÄÀòáÝ{S&NúÃï~
-ýnÝú[×®çeçT•”µÔ5èºT6­Ái0p¼=‹31£G‹²2aÃ#¹‹ˆÂ¢v̨6£syT¨ŒbÎh
-ÀŸ(RGÁ™dF^MDª'"í·(N-µ×wá¼F¡
-‹*I6ªr\4¥i*£ð»éœ™¬Ùd‹ÊóV±ù)Ȳᮂ‘üнNªjÖ®øvÁ쯲f@Ì ¦²LÚuvÆã…sæŽøtè¾»Úš z
-¢ÇAê¶Z½v;¨•4ë0Û›/è’D›…¢EñKð¨ÂÏ‚E!E‘z®ÆÚº½?ìy~ôÁ‡cG1ü³U+¿}–õ´¡¦¶«¥ Oï5ÙSkŒ)Ô¡Ì܉'SYÓvëŔʢJ…Z ŒBq.ušg¦,dJ˜TbÚd@: EI:³((´¯GÇ2zP(¤óhQˆE;šHRõö‘’t¾¬ ,ZQTƒÍË!Í|ïVöõ«`Ñý{ή_½ÿOüx݆õvÒÎxÜ¢œ7MBFoѨѢv­ "ÕæR&¥)si‚WÓÉ6Ý2ÒEi×”Åà.q‚ ~/äòpPWZ±fùJˆBó²²!
-ÅÉ#·Õn7š!®(*ٺốC†Íš6ýúå+Zµ†¬ir¹$n BÝ~Ü}<Æv|SîþÀÙÀ¢‹F`QuW÷õ«×¦|>ù?ÿãÆÿaÇÎÃ-Y´‚ÒCûöÃw!ò4kõäOK[1¡ƒ)4aob‘ÆF;™9Ùh‚Ef§ÜHÎj =(Ôª¤ã¢¶x7&~¦Ÿ‹GgÊæì6ôCý àÔXwùìëê¢B•…@”UŠX)Z]ÚXYL,Zú¼RiÑ;·ž^½ü,z`ï¹u«öýá?>ønó&´(6áå¼I”³Kˆ‚E-}fQ"RjÑ~‘Ò|“¹4”j j8å‘*#R¥EÁ“œæs¸Ð– É«×~3oqnÆÓ [ÀÍ+.?¨¼v·©ÏÐÓÖuáÔ¹YÓ¾óÙè¥ ¿~òð±^Ý‹eN¸˜Ç<Qq Ü Uið (.ÉCÞ¸rõ«Ùsþü_úðýÀœ'»wëvYQqöã'›Öo˜3cöõK×@w’GÀUH½…Ú8ÅÄz:‹&L$á-I j´Êk‘bØ vÀ¦ï·(\âA‚ü©œ‹W’ Pc—‹ê»tºN-™cR™Ei'y»OUÙ«ŽlšÜØ?.Še•¢U% hÑç¹¥`Ñg¤¹(±è•KÀ¢÷_³jÏï÷îÖíÛ!!–cÑx¸E9¯´h_O‡AÕÒ¢ö>ƒÒ¢}¿HH)ÕdǦËñÿ6”.ecp á%è¥ò‹%ùëV®Z<wþ³GYNƒ¢Gð•äôÁq,†$æ‘öv©Kò‹¶}·uÂèñcGŒYýÍêK§/µÖ7ƒH«Ò·Ä#ù¼ JÈú!UaBØÉ¶6Æ^LV£©¹¾áâÙs‹æÍÿôãOÞþó_¦Nžòý¶í`Ô¬ŒÌ’‚ÂÎæÖ¾nU}eõ–õ›Ìž—“ùB\›Áa$‰uS—'Ù XxŸÂcØ)Ÿ&^C–‹þÿ콇wG¶îû'½wï=gÎÌœÛ3ãœdYY²d˲dËÙrTÎ9ç@I bÎ9ç&‘0+3¿¯j7Š…î%ÏyÇ\ç¼>÷* ˆdÿðíÚ»ªGç†=)l—¤ÀSHS°®œž‚ú†Há(
-
-ŠBh(Ó”¼ý (ߥNAèÜÖó|P”ÆERˆ(ÚÙb…¥‰K huE#_¢¹:#­$1>‡yѳ±Û~9 Š?y‚ý=sŠSóâ<Bшþ{5;3.(
-„Žøzˆ¢·{ûT%‚¢ZŠ¢å3ͪ6ðÿ¯€TŒ…Ê#«p†dDqlmhÚúý_nú¬º´ðœy4×ÿIkÇ¡Íì(xyFú†ú¼‡Ù^”[¸wÇž–­]üæâ lØþãÖØ7Û M‹©·Ç=<4pïîí÷ïýzïÎÝ;cwnöõúmV³±¥5éVüÁ½ûÖ­^ó·¿¾ðòßÿ~Ü >&¶(/¿¡¦Ödìpt[¼v'8,ÛMV€ô»/¾©(.gë)æwïß½£u¡ºƒ¢2E©„Ž Œ„ͳ«J©"NHÝÈ]RÆÏžA&MDO… UÂy7K$±{>.Êw© È¥Eiâ’(sêlae¢ÔEP¨¢¬QKÑÿøÃËgΙä닎G(Ñï,xÑáÑ÷z]#NQ¿UööHO€”©ˆt»oäÔBU—ŸÚ_;pΣ΃Y‚'…óä?i‰f„ó”<2ÔÖÿôí–¯>Ý\URÆÆ6ï>$„<)®G¾=¿1#w{hl¨wÐçõwu˜ŠsŠÏ8»ˆÿÝ7ßZ²èÝ5+–ºáã½;w\:wöÆÕ+8ž9q|ÿî]_|ºiõòeï½ýί¼ú÷^\¶øý¾ýîäÑc 1ñ
-¢Ò’ËÄ[ÊÑhƒ°¦›$´Ic82–²ü‘ è<“ßE¯ò™Ê,ø`CÅK¢°]F¨¢PŠòáЀ–¢lnDm&ŽTo/ô¬^´Ñ,(ZYÖXZ\——S™Á7
-¢‚·€$@
-Š"¨¯(*ùf󟲩®¢
-¦ôá{°©x1;䤸GB+ñm9ÄKC¾FîÞîô÷ƒ„~W×îtt[,]&cGW»±ÍÐ ®ÖUU7ÕÕ·6Z›Œ†S›±»½ Ökw÷züxípï ñPç$3)*?M8Þ¾Þ½
-óUÕTíÃyÆTuÇWñ*Q%³ zwt¬¼¸ä«O7ÿôí°ôÁí»DW%;Ãm'‘GÑ AQ¢+ÄÖ=æO¡þ»xGÕ‘¾!NT_ÀíQ=6ÝV;=WŸË×ïöxC=}c½CTGÄRäƒø´wäò$šž ô! •%yEŸò¢{S['B{À„ÄKð¾2-©=OÞ†Fú‡¹FGûærFsóŒÂ„ꪴ»Š¢­‚œ²t)ÊÄ)Úç$ :GÑàŽÉ=„P¶Ž7¢2E»Z-TæµÔ›E+J@ÑÜì
-Dôq±YW¯&œ<qý»oÀ‹¦¤%ϰÑ™E#úýEõ¹l è`gÈëQQt¤‡ÙQPt¬w
-/J
-l
-rRÏœÐÏâúQ¶…1_ÞSNi™)gÛ…d/*Ú²tGA¹ÿe²÷õÙ½² ^
-äeŠÒ²Ì‚¢$¾ Û"„(ÚÖh"ŠVWdЦ¥ÅßÊADO^ô/y½ (?ÑG´Pšžy:6:àuYû|ž¯»ßãB]®¡ß°ÏÏÕ `ŽøûÐ,•™)$?%Ôa¡nPj®ÎoV€3½l©ûˆ¦ùDT*4¥±PÐ2/#ëËMŸmýþçÆêzJÙmD8¬T…Έ’7 Vm¬¬Zì¡sn°KݾG;fBôP¼Dœ©T…΢ТÂQúÄF²šC¨‹WÒ §Îù]=÷øê\,ß?HÒ,xÅ;Á­âtŒÙÉ‹Šl‘¨ó¤•—Ä*v*‰sÔå Á(^˃Ÿ½Ž@Àî÷9|\~+u(©yVÝdöâÈdæ.ÔÒi³v0YÚí¦[§ÁÖÑd66v·Õwñˆ¾£®^´‘S´.'‹-è›{åRüÉcQ›7má/o0ŠÎ°] &¦Æ#è÷QÔã´ôö¸‰¢l\Ôãê €¢€'±‘ˆJÒRTÐUÅUŽÓ‘PÍGQ-KÇüýGA$Ð`
-
-HùKÄZI⡘"DÕHÈê: Ÿ.ôÚ…+Ÿ®ßˆcŸ7€`ý +s¡½|{MVhÔ¯äܥ͋u)ª*URq’*ÖÑ‚T¡só’øJw~Ä|¥Ò»Ïkëa
-RT$•”5™yR ,ín3[ŒV«ÑÑÝjïh²òeE»´-*¨ÍÎ,EoÅä\¾xëÄÑk è‹}³¨¤m25Ãç.éÚÑ…¿×"ú¿Uøö¾=6(S”…ón·LQR° m4H”ÊÁ¾Ê©JÁþ³)ªMZÍõý ¤ÊDT×ã²,ê)ÌÎE ÿýWßÔUT
-°üT`dˆÔ Yg^K$ñ’$•dÊ¥ž­ºþ3¤–‰§ã… ¥…ëU±<ê±øøFÉ!?E!S»¹³¹ËÔÚˆ…e…Ôv4׊–6U× Š&Çç¢ÏÇ;|eÝšoÿñ·w -MDÑȸhD¿¿ˆ¢ˆèý'Q^tØãéw{¤DQR™¨§­Â—
-k*5›Zk:ÿH)¡ÅÕ2’R>]¿aÇO¿4×5À…ú¸ Dƒ¼(¹P4dÊ&HMaèw»WÑX`eÑS$ÕË Å£œlcz¹žá>ÆÒá
-¤²)•­©føtPñBqÄS·Cwz‡!ê¡g½½xHí‘AÈïñ¦%$múèã­ßÿh¨­¿=8Ì&øóÅR”‘r¡ªZô XÊ&Ô‚Š‡’o%§:Ôˤ¶”’´ý ’}x;’Ð&‰œÃé::êç[¿I•):àïê @hà!4Ü7T^Töå§_|±qsqNñÝþÛC¼$¶¨ìwØ"Kî>`8Ñãê•+äe–²Å?}²Øâ!\hås¨-Îaó’ìˆòJ";/J›Ü6/‰–%„ŠÍ• e‹£ÃÜÆÊDΤœ¢” ‡EÐúòæš’F¢hAnEfj1(}á\Ì‘ƒ—V¯øòÕ—wuuÀLF(ÑBHP4àqŠ"¨'ŠÂŽrŠúxrŠê‚TàE…/*eŠ6à¤xˆ6Œ(LÃ>æco õõÇÞ¸ùáª5»~ÙÖÞÔŒ@¾¿ÇÏøéïõx <"aSŽë9E‡C |(ñpTKn2GÔœ ¾J¦¨Š¨â4!b©r²_)tçû¶©$¼(4–òú8—Bw†o—æñÉß|öMmqõhpn& G
-Zö9ü,`ï`ûœ-?[H…P"$¨(ST÷¡½6¿(m’)
-Êæxr1„J{‚%Š2/Ún'Š2/Úl&ŠR(ÚTÕ&S´¬ ¦ §J¦èáW.ûüµWÞ7›MŠF´PE>ºK¥ÔG¨LQQTxQ¢¨*Ò—|™¢‚®„Jž›à¤xv¨àíHéHD½pßHŽOX½|Ŷ~êli£~ÐÏ–œ‚bóµA9©¡’LN‰¡
-KQ]/*ÓR\yÈ?¤¦¨?ÈpŸR‡É÷mI© –‚Ÿ$— RâlÐ7˜›–»ùÃO·|ö­¡²ñnߛώ Ýá-oFúYÀ
-œ’%ŠBCÁU„ó@¨°¦ñ1±¬\µsë6S›‘6>ƧH¥:¢¨`©üpN—¨ËÕ!aýa%{
-|ù (µ!ÐG:™Fµ“.Ō˞:_¼– ôùþ»Cwq…œ¤¬uK?ØþÝVScç˜oF‘†FÜýÀ®à5{ÐПä®'#ŽºÕ"”(*Šš¨Au™Ý´‚=“„PAQňv8€PS‹GccJã¢AŠŠ}KUI(Z\PŸ]™™ÊÆEcndE—¼·ñÍ×—y<®E#Z(¢ßC
-‘ ëó(7w=fÍŠ•{vììlkG o<ÜÛO^”]…•—ªRu
-¢Ê=¡@VÐÒìrý:LØ<Ù:EÇxõ;c)Õjr`Ò™ †Þjó—«'TÊ3‰8]„ÈLâˆR¨ÎNÝ}‰×ã7}°q×–fƒ ÅË5A<¶óf0Û®å¡x(ƒQ¦h¸sžr[ÌNb¹$ŽÐŠá)ÆEi8TEQHCQ(ÚXÙ^_©P´¼°–(š‘RœŸ{3*ýüÙhPtñ»Þzc¹ÏçP4¢…ÒôÌãÇO~E}.ò¢ž^‡íwziµa LPtР†UO
-œ‚œ2E90EY~?IP”ì(Qb[Åõô“
-„Š žO!² ²•+šDüNb£dS›G´­FG°ÀI çiâ'…󌢭@hEQ(ZS•“Qž’Tp+çÚÕ¤³gâöî¾ðÆë+W¬øpìöÝ™Ùéñɧ
-Šö¸m»9à´ƒ¢<¢ï™‡¢rD¯¢¨à§–¨*wJŽ/Ž´O1<'ÞëÒ™ +/;°kŸÙh¢)ä?U¢[ñ”ŒJíÉÚW©ÔKG·2p1LåÈdÉh ™\9ïò*Z>ó4m=’\Þ)òéh ú†:Œ»ܵîý¢Î^óš=ÃÕ õ{äzN˜R›bæ;ᑊ?µ!ÿÜJ¡R:žåâ¥PÕXèÜ’#1åSIÍÃ…r_Ê—Â3 ŠR±½Š¢U%M
-¶Ð}lÖåKñ'OÜܽóÜ«¯,Û°á‹G(ÑB }:þ
-ŠÒ”%™¢5eÍ‚¢9e4./zâø Pôå,Ù¼ù»ÇOÆ#h¡¤¢¨ßfE6QÁ …œŽ9»$Xª) õËŽ”8qSŠþ{ƒÌsž?yöƒå«<êè¶BÁ= U8RABV9À½h¸=Bç‰èE5AR)ÎäÕe¦®ÂïÏœ7¤ Im¿x MsˆX^ÞÚƒ7ºím(«ÿîÓo?\ùQR\
-í‹$L&0(RH”¥¥¨ ­<5‰ª¥¨\T/…¡ÂSv©³ÅL•Çò]4ë“E‰¢4k©¾¼µºÔ@ã¢<µÄ(šœ˜Š^½’ŠîÚqöï[üõ×?Ñ*÷ŠF´ EÇ'ª(ê·ºRXDPƒˆ¨­dSeGªëNU •):Ö;D ¦#wÝÝv tù{KáBÐÛ¼´^TŠ\’vÀ=!$äh%=?]`=<®ðÏF—VðŽ¢Z*ÎM9<WM ’%Î'râH’#zP
-X}p¤yåß}¾å“7å¥çËåI¶N;¸
-*k†pBÂaÊ1¾À&¡U ˆW©(*óSÄïÔ¥¼RGs7=$жÕw„£(•9•ÖE³ÒJ“ò@ÑkW“Ž»¾sû™—^\´eË6P2âE#Z( /겚DD/(
-='EÃñS2•)Š×Ò”y´Ï>±zéÊ“‡{ínÚæ²Çᡤq,%3)W4‘#ÕM©úeÆÒP€Ž<~Ù‹Eû¥(¾_ò¥óà´ß5
-“é09‰–ò8§0™á(ªò®¤*Š
-„Rj^ˆX
-„
-ŠÒè(¥–@QðSEQ ´®¬…ե豣Q;¶~ñ…wüqçôÌl„¢-˜fYŽÞ×ãtZº˜µ;üvs¡6Pævzzœ0?>â§Ïé&ƒ*ƒT…S3 =!Oï€Ã7 F9}À&Áml`Äl49vjé¢%ÇsY·‡ÆdÃ)&…+UÒ-gÒž,.KÌ”]«¢6Êpñ""ƒ•ïùcp¡¼•‘Ò¶Ï ï΂jgiWŸ“…N1ª Núݽn›7?«púp¤e…=è³y}®
-(Žh{=\l±eª¥÷Øü^{@ž ¤*©%y^’âB»ì´'kðÔ<çÁR»Ùèîl±·7uCm­ 8¶5ššë:«Ûê+Yvž¥–Ê›ÊKêK
-kxv©"#µ,9¡4îfÁ•Ki,¢ßyòÅ¿¾õËÏ»áDgg§§¦Ÿ,ü Ñ¿ 8Eý>(ê³[}6»Ïæ”)Š{Êoë‘)¤º,eŽÑÙ3ìíë·÷ôÙX*{ŠÏô´vš¯X¼ìÔÑ“n›k†Srªú%­ÏSÔ¤©2U_óZ%¢÷ñQVɤå4Yö<,-ítDüœG
-¢ƒ¢À\ÀS„êÚJN1D©CŽ ¥ñLð0àéëëÈLÉ&–UözûAK,BiýO¢+ÎGÛÞíôؽøÓzõbRíà©Â¦˜£$׈*³ãv±”=Û™Ž/h„v¶˜ùÑÚÕŠ‡®Žf° Š¡-õF[º µÆ†ªV¢( çùÊÅÕTrO½‘íJ"úm[‚¢;¶ïEgf¦¦gž.ü Ñ¿ fŸ"¢øq™@Ñ« õÙÜ~«ñµËá&ŠR€ßãpEeÊDÕ…ù<ýV7XJë™ –wY‡÷BO=‰7ELÝãôª@tb¨sž<{¸½ÖÙ
-+S”ªîÙÜL÷
-ŠöX=V×3)ªe©nÊG×»x ω:´»ìÚ·lÑ’ó'ÏÚMVeu0í®Ê‰Ñß”6’Bç-;ÍËŠ©ú½|ö:í[ä¡%Žõç…ÛÖMŽèõAJQ±Ü±Já<§v:¥¤,¼(ã$„Œ›ß¸½fùÚŸ¾û¥¾ª‘ž ÑÓ^Æ„PôèRT5»SUW/çå…UŠš¸ U@Ê E»ZíM˜O™¢0¢<œo!в}YciQmQ~•Š¢W/§ƒ¢?|¿^ôÐÁ“,žŸžŒP4¢ÑÌì„–¢³C—¢ˆèaSI*œQugÙ³ÙIÊcsݹcní<¸cïºe«/<‡*d"ÐQ ¨*Ûþü0œ§Úë„ôsŠj#úçœ|4'½œ~¸qQHòªl‘¶I&Åïª
-2Ã…²ÍéÚÍ4åå…#µk½¨Š¢äEu)zéB
-"zPô…¿¼yôÈ™E#Z@ Š:Ì=6Ëü……M…tYª›o¢º}`Êçê1µuîüyûêÅËo\¸Š—° nߨÀÞ«W2¢"u®Êªëd…ž¥ç,Q´×Íý$ß{ˆÓòÙs‘T“âµ³™äT>kKû1…ÎŽ’Sçªâ"’
-§44ê09qd™&>È Ñr~woW[÷Ùç½¹xÏö}MµÍ@+˜Iþ“²K£ÛæÙ% Õ]õN€Tµˆ×óìÞ"#ÚÕj…:šm (O-1Š6×µCZŠV”6h)s=﹤Ço|¿e(zâøyŠè#Ù¥ˆD|UÆG½w]^«Ùk±z-v™¢0'>«WPÔkqB‚¥á|ÁRªÛïqzAÑÖÆ–½;ö¬Z²Åkº §ê2ÙðF,?îöùœ^Â&•úë–$ÍW­$I¾Â<Pý endstream endobj 725 0 obj <</Length 65536>>stream
-§)*'˜BˆªKNY¡Ûh†›8¯ÝU3WIö.e—РˆžKe/NØÎ^o?Žûw|ÿ¥‡öiml§á6Eô8ÔuYÙ÷¦’r2{UüÔ •ù)f')KŽðqQ ´Ûh¡)K-fŽP JEPÏGDŠòAÑf TEѼ¬Š¬´Ò´ä’Ä[Å èù³¬êþÛovÿõ?ß8súrd\4¢ÔäÌP´¿¯õXº=f (
-Nú,„ÛN»‹(ê·2çéµ;‰¢RAQ†Ê0,Å‘es u[¾ý~å’WÎ]Â9#þÝÝvšDÖõ8<2
-£H¢žuš‚¢‚¥h3é44Î3ò‰ðÍuM?|½eͲU7/ßôX==4É”VÔ'¿JQ¿ßå‘p{EC–ê´p’OV]vå“qêÖÄV˜2'eǨZ[I.ûÔ݃˜‹Î;A>\¥¨îÒÊ<÷Ô£Jè3ºZ|r9(/dêi¬1ìüe÷òÅ+Ï?G=@yW€…%_ê±ùE!¨\*’J4»“ì( {Š9ž¸&•ÙÃRjF«k9 ¤T,Šp?¡¦švŠè ¡Á‰Kð¢ù9åA/Zs#ýáƒ×¾úrןþøjÔµ8^/:9=óxá麗þõ4=;ŠÂ‹‚¢ˆèÝÝêí°ˆ‚¢¤„G·Õé²8p¤~:ÂFRŒO¦”X
-ؤ#}CM5 Ûܺbñ²è+ѸÙá÷
-á ªîT&v§h†ýóÏåTíû6ßü÷gÁS5.ª¦vÃ!Þߣª‰"ŠRPO,%f<}çù~Û²÷Vœ=q‘rÁDzèmö¤“LNyáP°1d‰¥T
-ŠRR©»ÝXž(**S –95 ŠV5”æWËæf•f¦–¤$%ÄD_Ïýã¼rýz<QtjúÑ‚ßPý jfvrrê (j3Ñ»LÝîn+(J†´tÛ\nŽJrž@(‰@*K0ã¥
- ?kí ØÙÄ(¯Í ø>q¤ÆüÂu gž¦:?¬ˆ½ÊÉ:$Ôe£v’f8Š>Ϥ$]ZªúukG9?½^m)©ÅGÙvQ]f¢ mihÛúÃö¥‹–_>w•8õKFíönYS˜O±.“ØûCU×$»“áIA=ø‰øf}Â|’ˆ¢Á)K,AOƒ¢„Ð`j‰ñ³ºÔ@K‘”ÔæV#¢ÏL/aK4Çå¢çÏ2Š~ùÅNP4&&™A”Q4’]ŠhDÙ¥¾^¯š¢, ìr³âmR&I^”(*@Jrší8‚E¶. ¸ŠFeqùן}ùñ]>{`Bí]v ‹AÒêõÛzHœ
-„ÎQ4«ŽQ4=?%9›S4ûÌ™ônnútûÿú?/ff僢ìy:’£h!4ûxrêáðP¯µ«ÝÕÝŠºL6·É©¬ÁËæ\+vTØN¦LQG·Íë@ heIv·¯²¤âëÍ_-_¼,úÚMØK˜Og·ÓmqSÀnë´Sq¸¼v¥Ø®BÆÎóøÌyNþMב!æÕ›¥®êÔ…ÿ<C®×ÒR@R'*å§¶äWÃQ”ö‹ˆPhÏpÊ)J³ASÒÒÍŸ|‘™’ÝãôùÝzŠ˜©Ê(‰…ïŒ
-çI"Š'ŠšÛÅÃŽÊQ¼–¢¡F´)Î7–×ç7d7ædVef¤¤f)= ŠnÜ´íÿýß/ääE#ŠhA4=ûdjúÑÈHÀÒÙæ4uº»­Î.««Ëá4±‰0¼ÚÐ)SÔa¶“ìÝ6ÑÑC€-ÈÎß´~ãêe«bâ{½P…BqÁ¹½#ÉPsÛU
-çÅph0„7Sü *S´£É í5T·B¡F´I,q_ZT]˜[——ÝQ /šœ’—u5ëÌé,Pô“[ÿŸÿõל‚bNÑÈ"¢-fŸÎÌŽ àE½V³³Ë„°]±£&ÓÔÃïG‡ËÆœ'›&…ÿ¤ì5hP4?3÷³7­Y¶*39]Œ‘²óâ”…2оæxºðo¸ùãZéÚEÙª`¸ 2ÂI»"1}<…®¡S‡¤ÜÊx²ZÁ)œÖi%f¸ëFî˜l°EO.q’¼’,*ab Î-Þ-¶˜¨¸¥‹–±éËê²Z¥'
-~-íõ–ΆîŽzSpD´ƒ(ÚXÙ\_i€ê*šˆ¢U%  (Tœ_[˜[“ #šZ’–R˜œ˜“}íJÆÙ3Y{÷FmøäDô¥µÓ³3ŠF´PšœyŠRD¯GQr>§ÕF3m]ÊȳáP+">+h‰vi~ñ§ë7~¸jmRlúœ^X‡ÉAS¿¹(û¯³ÎÆóSô™< GQÕ»<'BÅÔuÒy>I8Àª(*;L]{9T¨¤Ü:ÄVúi.“4Ï=d_9³‹jDE©©½;úZÌŠ÷W~÷å–šò:ôÓs.‹ßltª¾£ÅFX›S”ï6¥‡Áì<§hƒý§)šš\ (zæLúž=×>Þðóÿþ·—*«ê#^4¢Qtd¸õXº‰¢JPt¨)Êà)Øœºiº½ÅQ˜¿aíúV¯KŽKÄCp§‰ATP”øÃ‰äää¿<Ï#•¹UNFh8ê"Q¬þ¡é<ãÿŠ’áTIpRƒPµE%~ªÄ@Ú­W›Énî°Ø»>—³'ν÷Ö⟷l5ÔµôzáZ»Ûm45‰êBÅÚ¡Ju(O'H;šLÁÒ& !”obÖ81ŠŠˆž
-5V#oE«KiPTP4á|J1Q4&: =}: ]ÿñOÿö‡¿×Ö"ã¢- @ÑÙىё~Kg›ÛlEÝÝv¢¨ƒÛQ~WÚ+K'™]Ëâaí4Ô‚“¹éÙ@èª%+2’Ò
-rªAÑôä"AÑ«—ÓY¥Ó¾këÖ~ó—¿¼ÞÖÞ¡hD )ž]º=6H9zGg3¢œ¢ö.‡½ÓÅí (jvš­6Ôf¥½Ûæò»}ÉéÖ}¼fùêÌ” šåDU£vDý h—…ê ì]v‰,¢'fŠNñ0œT¾î¤ÒÐxî:Ï«­Ýo”ÙÄ¿E2œò‡Q½c8Bj?’ú½\’ªfžå‰ºÖ›­ߌ.‹ÑŠz,F‹¥Ó†ÔnèØ½mï¢7ÜsPå«”¸ÙêL<¯ÄEÝ–—©Í.J8¥à—†Ê¥ç;Z댂¢bùP”ó³ Š6ѾŸå
-E³Ó+E£of^¹”vöTÚþ½W?XóÕ /¼ÞÙe™ž™ž¬éÑÂhö)þö@QªE5E-V¢(`Ç‚è×>¹sÒs7¬ûdݪÓ“2‚ñ …û'æsÌv„ÿ¶Nvµ I\j<>Euýª¶sŠþV þÓüT’;|¹9¦à?_¾¦
-¡âd6Ÿ=ÌêÇ!×Ô¾WhU§ê
-òÊu–v;~¹V£2·1œ‚¥ìã™Ü-ˆ z*Kªøæ'„ö'œ6µ›ÙÆIVZ&”_ÐÍŒh›À ÕRð$¤h}§XÁ‰(Z]a€ªÊ›*ËË‹K ëK
-s«ó³«@QŠèãsˆ¢§Ž'ïÛseåŠÍ/¾ø†ÙâàËâE(Ñ AÐôPÔf2ºÍ&PÔÞa&;Š7xÈÂy«ÅÑm±³[ÉBÁf^f>ø¹zÙ°”jJ‚œn›‡²4Ú#ÊıIÄE„ ×?Ô&SŠèçÑÑd>3šÖ…Kèt9iÞ]ŸºšE?Ä6b µ=ùG¢_UÛ)y*jsXÚ(jj±Ð‘‰»MV
-er
-Têzι ]:AËLÕúÉ,ÏΧ½“È”ZXÁ¼•(jïtu:éwŠÐcíÊ—½·"ùV*U=Ñ
-ÌðŸäE©œ)XŠvgkCChCQ”/ÈÜ&S´¦²á¼ (+¹O© Š&ÜÊݽýܲ÷7¼óÖò€€íÊ-Á‚ßPý
-x³³“Þï0¶YºLTÂdm7±<B§•F8MíÝ´xofJn¥ÕË>
-
-Š‚{à§XTÄØÜI¿Mð ݰncFre ºZ-íM]”W¢ŠPb)”(ʆC:BÚ‚.”QTYÁ©¦ .T TDô𢥅 Ôƒ¢9•DQDô èͨtŠèwn=³ä½õ‹ÞYÙD@ωè#ZML¢ÓOž<êî2u´á9È›ZMtGŒmMè4¡‰±I¬X»jéšô¤LÜøxª£¹Î$¸±£™vØw±¼ì9ƒªQ–ÅÜ®(´ßª¥« ÉgR”ÎÇ^=vi)Jµ
-­üd¼¤› $kî:¼­Ê… ‰fÔÃlˆ ˆMíe5×aü¤Ï l'ø"º˜ ~T³Jè 7<2÷0¸rpÞYlÕ!·åyn»XjIdØÅs’Ldeé÷¡h4Õ6Þwô—ßúîËï‹rª,|Ÿ¶ÔwâË”*BÁÛæZSs]Ws](Š¿¨æÚ±3GhTSÑ
-Qj^-©ç úZ
-çù ú²Œ´ž gÓ?oÅf^¿š~ñ|ÚуŒ¢o¾¾|ýGŸÝ½ ŠNGrô-”8EŸLMMÌÌLT—UÕVÔ5T66Ô¶¦&e¯^ñÑŠ¥kão&ãÖ€©¯4´7[ëÛ ¶ú1-Gºwˆ¥¬DP´›Œ$Ü€óˆ`+óV U°CPw³‰z„›åÔe"?S2±Vê¡6ñY¹2'°¬p,{I¨µfŸ6xAñùåÑÜ?ž’FEd“ÛHÝ­öàbžÝ¡k{ª{:‚nS0SFhhÁg7ûŠ_ˆÍ¬ì¿Ç–†6ü|ªJkvmÝóökïþøÍöŠ¢:JB˜ð™ôÛ'ŠòÉòm ®¡¦¹©ª¢цªv¢huy ñS—¢4.š™^š–\"Q4ó¹Ôc‡b·þxâõW—~¼~ó½{÷‰¢/Ñ‚hrzbjfr|üÉääøÌÔt»¡­¢¸KKÈZ·òãw^[•€¡»ÕÚ\ÓÆ’u­¸# ¸ ´™Ø´>vsÑ]F¢BkV(ˆû®ÉØÜØ.D=ó«ÕС¬I`‡5šKL SsΓXj’骥¢(о<l«Ð?«b¯ì™dY2ÍTˆS=5ç¥4®ø™V!yê ¢¶SØW­ó‹×IêœûZll§/;ñû…9/-(ÿñÛŸ_{ù­Ý;öW–Õv¶[ëÚ FCCg«¡»µ¡›(Ê¢øÚfе±²™)<EáHËŠëh\”EùÊ•Yéé)¥)Iœ¢YDÑã‡ã@Ñ×^YòɆ/îß¡hD ¨ñÉÇÓ³“¡Ù™©áÁ‘’¢òÄØäVòÖ+‹¢.F’p›l5òò&ÐÒP×ÜXÓÔPÝÔXc`£®…Ô\ßJ UJ¬ƒjnì€øÍelªo2ð¡WR³¡“ÔÒÜ%Ú²p.hè䡨I &tÊ 5u€±t›C-ºR¥ZT5Zʈ._sXlÁ&$28r²[¥pœKëbV«yÞB‘´
-„ægWᘕVš‘Z–šTšœÈ–"‰‹ÉEÏŸI;v(ö§-Gÿöâ;ß}ûËäät„¢-¨@“SÁRnGǧ¦fì6wâ­ô¼ì’’ªâ‚ÊêÒúš²†ÚòFpª,®ÅÕ¥¤š²&ZS‚jW j×U·
-–’•Li;‰n7j××´ï¾5Õ+m®i“AJ%ì°i2µíJ.ƒ0ȃ sC Á•…Té0ÕbÂÊÅëŒÒ¸ÁœéÕ˜´9C¼HˆIæàä§ô†Õ*ÿÌ>9»NµSCE5EƒUI]aÄæo’(œ§ùGdGYò½ÞX]a
-eŠ9ýãwG^záí¾ßŽ¿Øàú¢ ~7Eô¯©S¿ÎÌ>‚˜|Œ¿ÆññÉ™éY·#€[#=%·(¿¢´¨º¢´Ž ­,®‡ªJB«K 쎨˜["B#ÈRæKk*›Hô0EåÒdrÊb3y© $XÚlV·ÒÈ-Q”ÝÚœœ‚“ªÊ6­;¤J›rdAP£Mmãï"#TW”r;@Ha4¨Í¯ÓÚ^סÑZÓBmÈXßu4¡ÎÆÚºV9ÚÜ‹ÊTÔRTEH]EÃË(/gGð¤É‹"ro¬í„ÿLKÎ[µ|ý¢·—¤žíb _£
-æ/”iÚ¼MŠ0Bb
-}U³ò-¼<•F,%¨ÊhU,qZŠÝ ¾D8g1!*KÈeöjÝrp5¤Ö ´;d¹g '35't’ µ$£Rê)ýëäš%ñõ„p¡D}5 mi2µ4u^<õÖë‹¿»,úú-Câ¾­EÇ/Eù¢ä#¢lP´ÔÀ]h-\¨•)š‘V„ÒÜ¥ø¸¬˜›éDÑý»¯mùúàŸÿøêžÝE§¦#k:E´
-詸J$ 'úZ ªC%±)ýëÄ×R°ÄÇ9ÛѤ5ø9W)¥ØPÛ~æä•Wÿñöš•ëco& ¨/+®Â¿Ÿ™í5χqæZ, R”'è«TMI,JJÈSQôÛ/÷ÿñ/Ø4BшXÓ³R¢¨2D?ýtbúñøÔ#*"gkæàÌ ã7Ú òKâÓ/^¸~òĹÇÏ9|rïîû÷ž:qì2¸zéBÜå Ñ×3oåãïw‚²ŒÔ²Ì´òœôj(;­*;£:+ó²k
-rë@ÔÂ|°´\-̯)È«.*¨-/mª(3àÒ–³õ{IÕ¥¨Š7ذ€T-
-"ú¯?ßû‡û;þö‚Û…D"úˆJÓ"–'„ÒŽ´ø³H§ªS0¥øâãKz’ûÏ>~üxppÐáp´··–•Õ¥¥åݸ‘tîÜõƒÏîÜyt×Îã{vŸÜ¿÷ô‘CÎžŠ¾v99æFfâ­Âô¤²Ì”Š”D„i@kEfZe&ÏÃf³3Ëá`qÌEX— ƒZ À¢ºÒí†#ˆJkùVr´²[’Çþp5dYyñU3˜Iü$ÞRkqð†w7«™Fh(O_¥Mue¨¾¼™èJ¢ZéR
-œår/4D˜\a++Eé|I!|¾´RÑO.Eýæ­"K÷)PüdßnNñÝ·g×ÑWþþÖú?ÉHË64âÝñùÐMÿ6d-/V(J.”Ï ¯!#š—U­¢è­ØÌèiW/¥E¿Ú¼Å÷8-t¡hD .¡Ð_6œMEƒUãORUóäÔã‰ÉGlÏ»™)àG<ÅŸ^§=~zï׃£««¶ÎPPP‘˜˜yíZü©—ì;¹sû‘ÛïÚqlÏ®çÎܸréVltF­œø¸l·IzjqrB!ŒkvFeNfUV:›ý—›UŸS ¨æåTA *íÈS˜ËpëqƒÛ• UWÕTW§EuT”%J³pD'‰J¶è)¨¼¤
-ÄÎõË.W®¥ñ°”p
-–TAc!ž8S¢Ê‹Š¸%«§§~“DÙ˜ÔIi¸N¹®L”™ ±4„¬©hã
-Á£Åàâ¡8AÑW•§F\¤¤ ¾¡®«®ÆøóO»^zá_lþ23=ÇÐÐFÿdÚ\ ü$Ñ"x‚¢4wž‹Q”–"Ey™SÆÍë©W.¦ž=™LýÿÇùsW‚›.E(Ñiö)‰þƒRž%–β½C³Á¸ir
-aþ“‰‰§ (èútüáäÌ#ÚoŠÍ‡š†¦g™sŸ˜¹s÷ÁàÀhÀ?hµ¸êëZ³³ŠâbÒ®\Ž>zäÌŽíûwl;xèÀéÓ'¯=}ýÌ©¨k—So\ˈ‹ÎÍOˆ+HŠ/‚kMO)OK)‚-p[1§šY‘“Qζ“Ȩdcy5…0®y•Å•¥åPqn%Tš_]^X[VPƒ#ÈI j -)ÃÅÇe~ê²”•ë”* 8¥†¸ñS´««š šj„FUe#=¤†Vt¦Vpt20 •ðx¸NeEÄ*"ÊëÑ +‡»~ue«FmÕ“Iåg c’dœ`á-ÏÊR¶¥8¿Žá´º ×,)®Þ¶u× yñ‹Í_À ·á3Ó¶ „в¢F¢(}R½=~¹øÍæg×äfV /J½•rùBÊ™Iûw_Eÿø‡—/]ŒŒ‹Fô?HÓœ–`ìøäc‰™{ãS¿BÓ÷AT"óäÌp•›Uš£7;53—=Ÿ¼ÿþèè¨Ëå14µ–%%²QÖCO:pöÀ¾Óö9´ÿ‘ƒWNŸˆ½r!-êr6Ïa¥Á¸¦$ÀUxW6ÀÓXÙ™e9™%Ù…¹Y…¹%yÙìa~v%èÊr¾9åEùlR؈³¯LlM`t¢MÃeÅulp€àîFO%†­,n¤ÁĕÒX[àåJ<A”è´t%_AH5ßaþ!=/ªöŸÂ‚Šd!TP”øIƒ*´<=…6~nÚäV|ûÕ//þå•-ßüR˜WŠŸÎã3ø±+¡ÿ]ÐÊÌ0¢lúôŠŒ”âÔ¤b|™ÆÇ2ŠâoàÒùä“ÇöíººyãDô±1‰ˆèñ8=;Ž¿·¿5"Šè9Eœf?ÄÊMgLL?„BéL¸V¦Ie ¾éÙ)ˆ™U60=+ý÷ôÉÔ½»í6O[kwyiCZJaÔÕ¤3'o;|åÀÞ Û·Ú¹ýÈþ½§Ž¾pòø•ógo^»’}#õVlfb|íTž’˜“‘Z™V˜ž’Ÿ‘R”™Z’•Vš•VÎK[K³ÒJò²*˜k%´fW’í¡Á‚œ*B+…–Ô {œÝïhäÃÖÂIJñX!NT%áÅTaZ¢’"œ’ijóH°W–X‡S{qq•´WP."ËgJœF´ÔJP”Î$œ¢ÍXZÞ~¹yËß^xíûo·æf–­„M:G|©ÑW Ôà7
-±½B’‹X™SBqBœ2.J=(ʼ(þ ù·ö‚ßEôLñâ|…¢!ƒ#Á3ƒÀœa¼UË_…#|ìÓ‰Gb =3,ßÊçúäéÔí;|¾!›­§¾®µ¨°2)1óÊåècGÏîÛ{tÏîÃ{÷Ù¶u/ŽÇ^8w&êÊ¥[1×Óâc²ãr ÔÄ¢Ô„’ÄØ‚¤¸BVÝšTœšX–œ—ž\˜–T€# Àg°@¢Ô
-®²|V
- ºf§­e|ôµTŒZy–¹JR¥
-­Ò¨`]U€•1+÷Й*² ‰Wé¢/µçÈ•¡*˜/>[Û¬"”Rðt,ÎgÉ#€té{ëþú§×vm;‚—Ñæf–ãóÓO†ˆVÐîÉ)¥ˆR X±¨Ñ_8›xüÈ­ÝÛ/!¢ÿë¾/Ê*™g'Ù h„¢ýO–ò7"ÅOf9EŸ€œã3ÐÓi6…‚M‡"ó§ðªig>ž|ÄË^2ɇLépÇO<H=O'M³
-«Ivýñ“X¹Ëô“™ÙqVÅ:Ãì«Bש©_ýÕçó™LæÚÚúÜœÂ[qÉ/\?rèìÎí‡àZþqß¶_îÙuüàþ3Ç^ºp.úÚ•„›7Ò¢o¦ßŠÍJŒÏKq¤êVz(
-Ⱦf¤• …€YÁXw•%3–u°¥i;B4N(«(̬¢ÒY®]\òù¼2³žwªA-ŠÞU$—smÔ¯‚¹¨™×ÁÅ¿ðNñ±ƒ…ìÙW“V,YÿòKïîß}_"@.Oó•Eƒ_LŒ¢(šœP˜W@^4êjÒ¹ÓñGÅnÿùܺÕß½ôÂÛÕU ¬ê!,®Yø!¢ˆþi…Fâ$eœ“ûO€„Ìñé©§S“ÐÄÌ4„‡8NÎÎ@ô”h³O¦à+ŠB|è•JR'‰œSä‡ÃOãíØ¢Ó¿NÏÞgKOOß§IXSÓ¬–Oµf«¬ˆÑ
-Qñy¨¡­Œ òvn¬@: v‰ 8TÔ çxu=p04—kP¥¶Ì©ìoMïNv”xŽëT—·D]NXôÖª?ÿáå=;Ž¢x (Š£.E“âÐÜ›Qéׯ%áçædÜáÑ»¶]\¶ø³W_~ßfuãW9>ù8Bш"ú½47fK³H|¬v•Í ¸÷ëXo¯ßl6577•ÇÅ¥ž>}õàÁ³Û·ùîÛ=ß}»ï—ŸîÙuþØ‘§NÄž=éB*WzÔÕœ˜›ù±ÑùÑ7³o\ÏŒ‰ÎŠ¿•—Ó›Ÿ”PWœ_’–\ÆF\óÓ’ó²3Š¡ŒÔ(=%íüœòœÌ’¬ô¢Ì´Âÿ½«
-G>|hn鬮i,/¯/.®ºÿ0‘‘I!!G|¼ÃÜ6ïuvÚºvÍŽÍ®û¶¸yoÝâ·sGðî]!ûöðõ9}(ì°¥áÀº¦EF¤s‘}¶Wc"9œLxd¥ƒÖ)œF9r‚ÙpfZÚXø'²m$%á܉ä+À„¦%_v˜Ù.I>$Û–À ¯ÉçN£šrHzÒù‰çÀçÉä À–’‰@À¤_€¤'Ÿ%äó¯¤
-´VÉãHGV88ÛÒQSÛøêõ›œÜç/\NNI?x0zß¾
-K :¸?ÁkOÜö­‡Ö¯ñ5Xá$",<õ$(ÿæÖ&¢š°§,?Gún‹’±ý™VF· ìê{bò—´œà¶ÎºŽ ­õÍmµà“\&Ðù¡•h®¶kèc­míuõeå5ïJ*óî?¾tñJbBjDx¬¯÷7×Ýkœ·­qÚno³ÅÎzë'Ï­›ý÷ì<ä»/Úß;.È?!hÿ‘AqaÃ&
-M ;~ðøáCiQáQá'DBJ`Kc¤ÁO¨BoÂÅÇž9CJ&Ù”ÍWBN’Ó[‰GÉÏ.IŠ?MJ÷ŸÌa„ÞB®-JMº@ÚÌÞV—îI›ÜC@k“4¡Døn˜úï ñ;¶ûCª «ã±Ítäý$–|Â×GxèΧ Mô÷ñõ:ºkGÔ×`§]JŠ‹ôôŒÞ•”boik$^…ØŠbÁòs¤W_ž…QýÛ»BC
-èv2,$0§Ðw‹¹Òê=¹j›XuH6SÉÅVm­äwfK.à"œˆAø»¹©½´¤êé“ü»¹Ͻz465À?bÇv_×»»ºøîæºg§‡¿×A_¯p¯=ð3h,h»†…¤ I
- >v0$áPh0­‘áp¸´Z<”~8ìø<qŠ"È€rä$¸$–! q§IÓ
- ˆÙp à;a?Ï˸2»$þ<™È¦í½ú€`'» h‚vÒ¢Bǰø ð|ºoñ+¥)#=o‡{`Ò±óÀŠ‚·Ð ZѰÔÁ‰~>1Þ{cw¸G¸¹XY¸Re|}CÞ³óDO¾ ¹ÿ † òÒw[F¢~OZKÒÒÑÖm¥j3Ñ‘ocÄ‚gF²ƒÜï|“ýôå®à°nŽ7D³–€¥“ 'HNcëÚÖÖÖÔÔRSSWò®âñ£çÏe''<rx÷.ß ëÜ]×8»­_»}Ã: ®ömßê·Ç3Ä{o˜ŸwD€ß‘
-M?˜L ·ž $•`i‰Áºu%,-i]3Èýàø@ÜYò rÄ’ù“´À,¬h<°„…dbQ-4¤q1'˜V4öHèÈGE_çâ)BU’—Y°Ã=´·á8FXº¿o¬÷¾¨}{¢Ü·„¹8z[Yl¢ÈÛXohïø
-Û®0~K$9ôzš”˜¨ Òê3KÈÉîV—Ò‡ÅÅžfš_ÐÄ%l1L.Ù^%Àt³ î›p4Xõ5Nžâ"ê²s¸o
-g¯U›(Êæ.oß•“>¢ÄÔ^Ùng~Á‚ËF>f'?ÏŠ2¥·-¥G\ùÈéíÍäf¬¤µ„3Z=¥äÚ+æ\iu?¾ä^®¤gì{ÌåCuUÓËçoïæ<Ϻx'>.ÝÏ'l‡û~·Mû\Ým¬6Zš­·¶Ü ¬‹£°«Û·vµZ½Ž0Z­I“ïO$vÈ‚ WhZv5\I—W`c£€£¯„kœK‰á¡©@È!`–übÝ×÷Üj¶j=?Ÿœ´ä!A¥ÕV^½*NÐý¬Rf¾bˆé¿¶þ',X>S>ÛN~Zº›Ðæ´›‡U÷tr±{{k[[ éãÚAŒ Ò
-y‚µµ´ÒG:É-?èÛ´´¶tÖT7¿{[õôÉ«kWîO>³oO°ûV/'Ç-v¶›¬Wobg»ÅÙÉcÓÆ}Û¶úïÚ¶ww„÷¾(_ï#@ü|âü}î÷‹Ü4$ðÙj ܓŽ:’JÊ¡é@§<˜ÄÇ+\|‚Ëîôusõ7Xá4n ïÁS¶¸í++«ëüðî2Ó¾´6·6tÎ’.÷ôeeýN ,X°|¦|³ýd
-s´ûè(óOL!RÚ»ÛIÒ5‹\oÅpÓj!Í,M…ðÔç@VrŠŸ”¶Žö¶ö¦Ö¶†¶öú÷;ßÃï­­ÍD,ÖÂÀÒš›Úkkó ŠïÞ{”y.ëèÑã‡<<¼×¯wwvÞli±ô²iuqÞ¾aýžM¼·löÐk/l¯ú{Çø{Ç ô-Õäÿä ¿TR‚ýÓBöŸ
-žE‚ËO/°¢d¶žÒÊ”îjÝü] ­­Nú^W ¤!%wÁnio æ°Iw,¸Õ0ŒíMÌÀ,Ìð,°áÙI†rN$7ÚfXÑ&ºñ$[Åý_¶X°`ù¤ïž{ŸÒÓ §tõåû0Å]NV„ÀÐX¤ŸÕúª+rª XN¦_+=|+ó ¾×·667—ml®#&ÜÛI§P2Ì#@Óþ÷{ñbÁ‚yù¤íåïÚ3”ßÇ®ÖÎlµÒ­YÑŽdL5aT çT"”
-±¡U0’¤i_ZZš@
-¹´
-ØU`]‰Ÿp$¡¶¾¦©¥‘ôhíÒ–¶fbR‰Ük 0òt+
-ç›ú½x±`Á‚¼|™ý´lÏV]ÍQb. ØÒ`"™ Q m­dlâ'ØLr¯U¢!JŸ“"›£ä*$Òx’‘¬ZÛ-ýÀ0¤]cLõ{ñbÁ‚yùtþ#㥳¢„‹±…³KŒîù{èOžJL0µÓên«ä1 ýÉX,ÐL>eø¸’óÌ0,¤&› ¤Sw¿,<»„ ,X°`Á‚ ,X°`Á‚ ,X°`Á‚ ,X°`Á‚ ,X°`Á‚ ,X°`Á‚ ,X°`Á‚ ,X°`Á‚ ,X°`Á‚ ,X°`Á‚ ,X°`Á‚ ,X°üdá4àäT²5Q4r6bã4ÐWœrj" m‘“³©#HÐbbç–³µ³e“åa×_ÌFab§ÿé¯?ÔÁ+´–]˜}û²vª¿€_ˆBab·!¿ŠS%Ø­Ùh"Ý¿Á?[wiÍfÁ¶˜Í–M‡M‚›¸™ó› ȉœ=¸ô|z¨dD…DÙEÁmèߨ41»¨E@”*þÿS„‰ØhbdŠ&øF¡'ÆNažG~—€Ç‚obâx,ñM^O˜q¢˜•^þ«Ào¿i²1n Á 1O$PàÁôk²É¯‚Å«gkkdcjÂnîhdbijëÌN¥òåK‡š’¥M~Ê›ƒÜˆÓD$Øù©q Š(|‘eç
-´á§Ò$$h¢}Ì/.L
-ËØrSd%çs)K«prË‹ðˆªÎVXÂç$©+$¬Ïë¸JÂt…ärÑ%eqÉ™RfRæó¨Ò²N‹ìgÒ”­¤]„í­h&s5—+
-,0sæSæ4š«¨!ke(¬Ï'­¬hb#1‡&èÉé.’ås’â[­²ÜAQNAuñj~9ñUöæ|ò‹dÄød¸Ìä4›­¤˜ªZ[©rÈ
-Sù©ËDÕ)jJ³äí¬Éj-SZÉ7W{1u…“¶ÜPkÅLOÂ…“Oz‘‰&ø°²æÕSVšã¬D3—gfj©œ˜‰³†¼ÎBqÚr-!ù%K …Thº&ò«]fÐäÅ U…øœ¤uµåEu—Ru•äUÀ¹ªÂö–Šºô»×^i¢=SÖÑXr–²¢ÈR*Ÿ’â 𑵆„²áŠUV|öv*âŒ,Á%v*
-–ÂRºrbj«T™yàU6œ'©¥h¦«®þ Á­`!¦jKLÃA‡bª-$:{ºêÜE]×V°p0³S\9[VzÎr5E.sŠÈ\U)yŠ˜…¾¬µ©°Œ’ñLÑÙDnÉ3æ
-ËYÎY­Ì ^³Jü³Í„•–+Ìc”˜Œþ2]Ö¿Ëk9 ÉYÉRÍìVñ9©ÉJv×e‘é|EÁ9¼TPñÜÚ ¦uV(+:‰ÛQDVYÊJêKËÍP§*r›ó˳q*qÚ»PÔç,%ê…~‰Å&«e¥lÅì•V .ãP4[hæ hê ÇE2BÎØÐRYÑZDTÑLÆÜDÊÀLÍt†‘r0Sše/;[nîòéJ†2Nlœ
-&³„4º•“’³äÚÊeÓe¥e¸4à‡’ÐlnYÁyÜb ª£1ECÓF¶Ür…E}µ¹EÃ`†HW–äæk8iÈi™«(v]</Äe ŒæsɯV\¼¤¯Ë
-›(iÓ–/ÖQéqYqNES^;'kn–Ë2.*Ä/+¹ØÔœSVLx¾Šœ–Åj.ІÐ)ª"‡žœô,š•ª˜’&MÖÅ^Ü@tEÔÜN©ëDúiÌkË,’rŒ_m%§;O–SÞZ" h&`¨B×Öi¯¿ó/—iÖTÙÅü
-Ta}®Å=*ÞD<½âbÊ3mµ*q;qZÎætá–Qše§Ï žå9Dý ÚŠ›K™c㤊p‹PD–h/ýè¡ÌË-µZΊsî|e%E5Š 'ÍHÐv–¤ ì"N
-§¢§€¶¬”Íê…‚¦Ž3¤ù •í(Tc¹Y€š<Br:Óyæ³qΖ0“ZÒíÚ2ú6‹aöÌD]tèÓ¤7[|¾¶Ñ*em95*—§¨ýb}cŠ™‚“2ÅÔšË&'-¡*âh¾J4ŒÄD§ /#‰Æ¼
-x*é×1ÔìëV⺳t§W,0éºESLצ°Ät9ÅL‘Cë3nÅÆÙã:}ßJÔYSAG…S…º@ÉXÄTJiÕ,c%>^9šƒœ–ˆ8¨Sa%#Ç¥<]¦€ùè»(Ë/[I[e¨®LÜ,'9í™ ” -i+ŬĘñ[Òä”ä—RUíŠêªZ,2™?{‰ÚbŠæ2ÇeØ”¾®Òõ”wY˜•¦RjNª€Î3YjTÄ’ébÚKM—R̤dªˆV9÷¾Š¡f—å'8/Í ž6qhgÈÛðÍr[¬¥dôöðÓÖ¼i?ÃÛq«’Éšò«œ„€eaµìJÚ’šÄ]8¬aåñ)Ì•PTZ9]Œ¢®"$$øMO¼nd¦Ó í$V+óh[KoŸž•lAb4SƺÛ!.KD´à¥DÁSiºJRÖ Ìôœ‚æÚ ¡#-o-k­ÓÓN›‡€’·3S°t²6YPÇFÞÚZË¥©•œ­2g· «
--0W–ÑãXؽ^å@±.s
-TEó9TC^.Yª¡’„m–EQHEAVJHESY‚6‹Æ!C›%Í+K“sT‚F]›O ´VÊPÌVšÈ ñsØ(©èiJQ4¸Õ¤¨KM¤©ÆVs¨Öö2ug)Š™¤¦´Š¹‚ðLuG#!UYãÕB*óD Ä´WëSyf.1¶0]¨ikF5Òº
-§2—ž¼ðR¾ofV¯@‰}”Y«¤µç}’YsT–k®Rè“Y
-Ž«æƒ;¯š¥²œ{¹-'(~MME y-!E¥æȃðl-I‹U‚Æ
-fV<sáãÅ×ô»ç$(Óu| *Q„Íäå‰[±q›Ùu¿³$ºgJÒYÁrÎ\`½DÍ„]f
-êÈéqÚs€7·Ðj¡±ƒ¬¤Öjá>ó
-øi£Bþ”[LS€?ÕáO¡Ùöær3M+ò'`2x”$)f4-˜ G¿˜M›þ“¸˜mùSNzº,ø)ªAÿ©Å/Σÿ4”P„?çÓ:*)(ËÂ\$$H]h+.H5㔤͒¤Š[P(¦«…E…ø–H€ŸÎÂðY”¤*Ø/¤Jð‰ƒ³ÅÄÀ_…$©òœ"B³õô¤Á_õ@ýÉ I€¬Û,Óáo-¶@Ý ôwhò\"ú3î•êB*¼*Mñ™FB³eVQ—ñj1ØÈbuê0©4ƒxu‚ש²¦Ò*] ±žŒ· þ
-Ÿ—î§©²’ÊÎÊ2šfÖÝÉ ?½ }yYÓ©ÊÜfÔO4‘ͬäÍÌì@/I^‡Ó²ïçW‰ÏY›Þ–5âvZFXÂZYg`¼ÔB%>+
-MÑl…®lóÀ§É45•z>4ÆDnÀ{æ‡f µœOÒr¥º‰¼5§Œ’ò,M{>¹™Ó-¨Šj´y ½¹L’bÎÉ'Ð¥Ë}]›~Í™ÜEÑšªL¡è®4þ÷¦¨ETHWœè©ÁÞ$¯ÊbMn¥ÙòYQÐÁbi~voôOßïCô§ÜåSº°ÒëÇÜåã’"_vûï]b3ú¼ýϬ—ïTü_]b߇__b_BR/½(ðÓŸÊHÏÒå›)ð%ö™øqõÒýc“ >_—o¡À÷(±§À®—¢?ã.ŸÒå»Sà uùJ
-|·û$~F½Ìè÷öØ÷¤À×èòåø¾%ö1
-üÄzé»Aøóê¥?[ã_LP/}Pàg?•?’Ÿ£K¶Æ¿„?ª^zR _lò¢ÀgëÒŸ­ñϤÀ­&úïüý)ðeºôgküß)ðãëR ŸÛcß•_¡K¶Æ?IŸV/_<>ø½Kì{QàkK¬GGû¦ÀÏ}*,>C—ï@o*±þíE~°É?ŒŸ«Ë·QàÛK¬GG»S ¿ÞÈ?‚_¤ËWSà;•XÿŽŽÒ)Яí±ïL/×åk(ð=K¬GGá]¾ãtñWéòý(ð•%ö…øîõÒߣ£ßÕcà«tù.ø–û|
-ü˜zéïÑÑIÏÓå[)ðÍ%öYøõÒߣ£?ˆ_ Ë7Pàû”Ø¿QàG×KŽ~
-|©._GïXbŸ 
-`ïÁV/Ø{{ö_íþg¼g,‘wàדuœ©ï̧8S…CX6·ˆôŠÍsÙ8 ¤Ø¹åÔ„¨ìDü+výyÚì0è  ne þïäÏ…ÃüÁ0m"ôÀwúëÉZDÔ­nÑ¿èA
-Á™à6AEÓ5–Ʀ TäÙõµØ–1ãæñSE‰oì"bä—ìTa1vªBÐâߎ%BñÑgü+ÎNƒ¡ùĈ3‰@bì6NN"_P7Iv*EHDD„M_mÐ Œ¾ð}¡¿3õ á/üJ¿>/þù·ûÏ=߮ݧÏúÒS~ráÿ„S¾H‹ÏQÿ3KàKóóé{}éñÿ øÒ …Ž_zÊçÿ=Kòó”Ï<þÿ¾Jý/=ñ«oñ-øFŠ~ ~²¦¿20Ã1~`†cü
-À4Æø€éñ+
-À$Ç@ؘcü
-À$Ç@˜ä¿0É16æÈ“ãW
-À<Ç@˜ä¿0É16æÈ“ãW
-À$Ç@˜äÈ“y`†c Lr äŽ<0É1f8ÚÀfy`’c Lr ´ñ †c’c Lr äIŽ<0É1~`’c LrŒ_˜çÈ“yàî'òÀ$Ç@˜äÈ3y`’c Ìp äIŽ<0É1&9ÚÀ½N äIŽ6>ÁpLr 4€IŽ<0É1&9Ư
-ýˆÏ,öï^8ÝOüNªôÛ-¾ÿûÄ@_Mo Œ/Âç7°10þgð‰~¾ÿ¹èG¯
-þôûïüñÇï¿ÿÞuÐ7Ë©¿1ñ‘âþ¿wÿøíÿ5¡×M~ï[)æ÷ßÿøó¯¿!þúóâ˜ß˜ùý·/ÕœõTz‘è3øýç_
-ÄØQÃÙuðyZÿ®6”áØ±cFA%@½·Ÿ0qℱ£Àýÿ† CGvK
-g$
-H©ê­4^µb²8/ûø1c'Í
-ó‚e)
-û”iübòšº‹/P—á>yâTN!­åæ¶ö6¦K€R3 R<4iE5 5EiSgÌ–P_n³Ñc×ÎÍöZs(ܳ¸) F«œmL–hÎ¥Ì?là_}V7ã50tØp`£†
-YJ}ñ*ËÕæº*’.>šÌ¼ekÖ8X,×’žÍÃG£®ojçâB&ðqóRçj­´Y·ÙuÕ2uI~öéÜ4Y­åf6¶VFzÊâ³9ØgðÐdç/·°s°3_¦%Cåž9“[h®æR3[;‹•:Šâ‚³ùis5–˜Ú:9Ù/V“‚·–_`â¼m÷^O7R)N ”ÊÂ&fÆ+ªHSùg Ii¬tôØä¹f•¶œ¸ˆ„ü|ÛM;½|½w¹9®Ò‘d3äŸ?úPû·ßþ ,渉“&Ož4q(dÊ\-CûMÛwº¯·^1_^J\Zy¡±ó¶}þþûÜ]LõTçJJ+ê:¸íöõ#TæHH).0vñð òqw0МC ˆ+険lõÜí±Ñz™Æš „²žÙ÷=^»·:›,T” RÅ;mݽoÏöu–K5åçÈ(/0õöÞµÙÎ`¾¼„˜”’žÅÆ}¡Ñ±‘Áž.FóI¥VZ¯Û²ÍmµÁe™¹
-ZNž¡ÇNžÉH
-ß³ÖDWCUs±ÙZÏ ÈøÄcGìYg2_ŠgÒð}=Ý¿AM/¿€Àl^^Q9ã5žá‡ÃöïXc¦¯=Og™Õƽcã¼6Û¬ÔÕ^°ÔbÝ®#Çbü\­W,ÔÒ^b¾~oØÑ”丞ΆÚJ²
-šKWoö
-Š÷ßîh¨£,¯¤µÜÆÍ;,&îHè¾–úšJJšú–÷†FÇÅòsw4Ö_¨» \48:þh¨:ÓEóÔµ–X¹úE§=:ùО5ƺêªó€R;üC…úï\gµr‘îgϰ”‹7sne¥Eì]oe¸ÒØÖÕ;"ùlÖ•ìÌã{]V( ±ÜËûý¯À„Í¢ˆË(())ÈÊÈÈ«/6ß°/<ñäé“ áÞ›,L-¶úG§¿|åBzl ÇZk +§->‡S2³²ÏŸˆ ôX³ÚÌÂ~³Odêù+—Ï¥Ú½Ælé¢%«ÜbÒÎdž<ê¹Æ|¹þ2S' ¸ôs3S£ý¶Ø­Z¶l•Ý¿èÔÌ‹çOŇîÙd¿zµ“›ODÊÙK—Î&‡{m²160±só=}5÷Þ Ôžu–†+Mì6{‡'œ8u"!ÂÏ}­Ã¦=‡ŽgÝ}öòùý+'{o]ç²Ácÿ‘“—s=y”›zÐÝr¾8çØ!÷R<×ÿ°™Æ+¦0_¥¡áÊeKô—­²Ýìu"ëVÎͬô˜ ÝÛܶí 9zúÚ½Çónd&òÙ±mûÞàØSWr>º¼=¶lÝsòÊÝGs³RÃ÷¹:Ú:lØuàØÙk9¹7/¤„{¹¹88»î9˜tîÆ½¼Ü«§ãw¬wrÚ°3\õîƒû·.¦FìÞ¾}OPLúåœr²Ó£ý·o\»qG@ì™›ò_½¸9-Âk˺µ›v‚Ûdݼs3;#>Ìw×ÎÝû#S³ïç¿-}[ðàJú‘`/ÿ°cgn<,xó¶øÅÝó±ûÍáÏöw¯‡û·?þ<r
-¯¤úR § ›7oZ¿Æe­«g`Ì©kyÏóŸ?¸‘™u0ä`tʹ[_½yóúYnÖ‰£a‡Ž¤œ»ù¨ ¸øõÓœK'â„F&ž¹þ0¿¨ð%ÈaTÀÏ=þ)ï<ÉÏv7ûDt÷¯ ¨Ô¬Üg¯
- Ý<›æ·wŸxÒ¹Û Š^¿¸õtBdXX¸Æƒ—……ù®e=èïãææ“¢Ò²wy—Ó¢ƒ}}"3o<
- ^æ¿~SVÝÐÜÚÖB$ä¿xQPTRUßÔÒнèùC"C…e5 ÍÍ@©—óî?x’ÿ¦¼¶©¥µ¹¾òmÁ“¼{÷À𪭠¥ª¤(ÿÅóüÂw•uàMu€UOÀS 
-à¶5¥…Ïåå="NinW­()zýêuq 8£µ½£½µ©®²´¸ðuÑÛ2˜ÓöÖú²ç×’|IsëCí? ŸÂ¯°|­_ü…œ§ù¯_¼|þüEAqi¸];P³®º¼´¤´¼ª®\¼££­¹¡¶ª¢¼¼²ºÞ­£&T–—••WÕ6‚»·/)ff¨ &T•¾-*„ù×loki¨.{[øQK^VUyiiY%('xDs=8‚y
-8 ªY\Tô†<Üܶº²¢²ºœÑÑÙÙÙÑÖÒXW]YYU
-\³µ¾ôÙÕG=©>Ôö ‘ìTu“­OÞ|V\VYYT(«¨®:tkj¨«««'~¾ß rÐÜÔÐÐÐØÜ-¡±¡¾¾¡©h
-<W õ àjà\x1ëÖÖ–PkÄʼnËÒµÁß] ­­dJ·Û33•jinjÅÒF^ƒHèžeú5ºîBžBW< ­•¸FK[×) #€ð燺RˆŒAµŸ_KÞ¿v™¼ÀÔQƒÿîÙë&,Ú Q-ËQ™÷ +áÓÚFª@^P¢“¼ø¢(¼ïž
-*­Ü|åqq°[½®öÅè;CŸ>â_¯ñï§t?»³½¹öÝÓk©¡î«õä§ÚóñþíÃ&òÌѵõ<œqëù»ê&øü}¾‚ÿ³
-j“zW½y|5%ØÕHUhÚÈA,FíïA#&qKh™n>~íYI] jÃÇ»¥¾üUîÙÈVZ¢3Çôc¡W7MeåZ¿„ìÇok‘Q>ÞÕÅ.Æî±] Á:ÆÂ`¹òе¾Ç²½©iFFmØf)"Õ–ì¥6$ùD.qMãMÉWž¼C§¶ ’äž9¼Ãj¾GO’•=v†‚¾gÄ©[/Jë‘2iů¤mZ¥Je5¨‡Úü=xÔÔÙsX¸%f=(¬lD£½B¼¸‰Øað“á›Üs´œK›%®¹jƒo\&ÑLCå½M4Ór2c}Ö¨‚æ
-[÷qD¢ 6MPa©Óž¨Œ[ÏÞV7¢ÂqÐ(/uÿâ±ý®¦ó%Aã´'Çÿ{ÈX±yf[CS¯>.®lhA¦²›ªA[åømV e`WäŸî=îßþø‡m<·´®Ýž˜s÷^•×AŠ#¡6¬ì‚ܳÑ{Èw¯Žç?C'ðÊè;û&d?z)ŽDeµ[êJž]O Ùb¦EP¼ç("¡6Ï\†Ú »FeƒVóöñåDÿõ†j"½æ¸Áû‹m—$ùùû¯+ê[Ð 9¡ö›GÙ PmQÎ ÃY•à☙"šÀ¤¥]ò¦ª¡ “FÖöÐûÚb®3göÔQÀ¢±´ÈŽ˜" ¿Ôiß‘3wž¿#^`ÿ}½aô®ôÅ패½Î+ÔDgÁêþõá?KLÓdÓþø wóKU"ÆÒ
-d§„zØê+MÃö+ËœÊ/GWR.?(¬h@¤ºÛšjK^Þ½´ÅBGš—Õ“ƒìwr«,‡í´Û/iÒÇ”žßÉŒó]g B>zp/[NöE,·†¤\yü¦Á4øt7T¾yz#ý‡•¶ç¸!¬oA¥y&›³#2†ÇVšëÊ_Ý£{r°º4н8¤´Í6%]~„ŠÚ°º[*‹\Š÷vZ<—Õ“ƒpÙ;CHQßngxúgïÐx¶™#ˆ÷ÎÇìµ×“fui ,ùd^im3×€cî 2?@·iàÙs·Ðãè5”öÛ85ƒµ^GNÃwïmrV¤3x¯Y®D™Æ2¦[i“gË.²óŒH¿þ¸¨²>lÖ•Ü»˜¸Ùl¾$7áÑгM>z:MÝØ5(6VêQf
-¡öb'ß85€ÈË 6É+ ï‹Ùç¼\™F8q°øìü=dÜ,)]{¯£ÄDJj¿¾›Éð]:€Um8Ì ¦eµ#òìÝWˆt¿Hµ«
-ï_8ê³ÖP]Œkb¯±4ð9¢l¸1(åê“·5¨¼µ‰A%8^ ]v(ÓDz±xä1}vvE.Zh¼ÀÞÑӲüÜsq~MçKóM9¨W¿“ðÙ1ܰ?1ëaQ"S`åÕožÞ̈ڷÆ@M„ckŒðÙá³ÐzGø©Û/JëPi’ƒŽHEᣫi‡vØèõšù#åcg
-«mH¼ŒŽ1§·Nï_<æ¿Þ
-K½b/äV!cÔ`ìÍ“ëiÜLÔ…g° *ýj{Ȩ¶ãÞ˜s÷^£2¿ýžtL{vãDèS aÖ±4ðâ8l'èy®ó=z1¯©Ú®*~t%9p£¡
-ôÏú‹¥¿ Ýñdt­¶8ßÜÈ<ÛmÄ´þÙè=‹eYM¬ìá¹Å5W­÷;û`Yòò×y—@gÄXC”c\Ïé MR\ê¸ûðÉOßT£òhÃÖiñã«©·¯Ö;›µ¹BLôrIÌ7ß’‚Ð0ÑJ+}yçtÔÇeJÔcÙþù³ûòßÿ0|òlÙÅ{¢Ï"æW]ýæÑå$@qMq®‰,3ô O…ek|ã/å`ˆ¨Mö·ìqЗ˜6Šu”Aä—_êâéAa%JÏÊWÐqµŽkeË߆Mä£g·;ê,:0Æ0¡6}Ø´§ÚÄ0¹¨¦Éæà”+‹Ñ1äíMÕEyböÚ÷ö@ü?æô¶ì"»]‡3n¿,E¤ºáÈií»'W“6³¼³ªýç?CÇÍV5XçžntúÛ„_ZÎéÃ;˹Æ÷ZÁ «{Ä$)m‹maé·^”!â`LUºœè¿v¹‚À”½XNv<á;ì\<ÐÜŽ‚Ú°ºëËóïœ:´ÍL³W·óÿëõ¹¥ØìŠ>—WTNW¤©ª(ïü‘]6:½VL0ŒùX1- ÃgïV¡3«ßTýæá¥¸½öºR³úXÂM¼Ã8ÅæÃÅÌ÷ Ñqf
-µM×»æíÓk)ëW(ðO> ÷™ÉÜâêk¼ŽœÍ-(G‚äè3ûDËÜÕPI`JOµÉåo3„äYÃeè8ä‘î²—7ÓB6(²Ö6cõ›Ž¹ëþ£çr_–Ö¡ðƒ ¯ê½’ä¿f©,ßÄa=žm2ª-ô]ñ‰9CĤhC„ãD“åÕÝÌè]6pì´Ç1Ñᆑ8÷Džºñ˜Äü@õ›ÇW’A7L•u'Ùóg¶åÀñ+ŠPñ]!½WêËòô´ÕÃ;ixÏV\4Á%µÐvW4°âeÈ<ØôY‘GÙ‰û7ªÒfŒa Ž÷ÏÐ Üs9ì‹»˜G*¡¢vx²sÏDzÚ•=°÷Ê .i]»½±î£ã»B°”½¸•ºÅTS”s\¯Åú䨒åöðS·z{ÑÇ•n¤…l6Vž9†uõ6SIHyå:ÿc(yhýKmïí‰ÜR:–îÓ®Á¸¶¨¼¶?ùl3¦E–8ìŽÌ¸…Ì}ÝßÇ,9}Œð'÷‰;ÌtP×{û0½º{­ˆ‚=0^)m‹­R¯=}WÛÒŽ„1g¶Ò7õŠ Hl3pŒïºÜÙ;î\>€
-ËÉYϳ‘žÖ:½"qÀm’ ;]@v‘-1ÃÄXYݲù8볎®@­²šÄI•_lëyøtΫ
-DÔ~ψQž¼Ý29¾IÝ;žp$mܸMPZÓpRKƒ:;àÂ?Øß^ ÔîÞßþíw`φcç¡ÉÌ[aç’ŒNÜr±¬€ 7Ó“äÐqeøø’*zÆNÛfÞ§(Xrr ¼ìõÃ+ÇC·šk‰qv0&#ÚNœ;o…ͦ=¡ÇÎÞ|·@á½ ×CÕ­¯¦Gìv\ª Ø=
-*“"Œ½ia;ìô„ˆ¥­ÝÄ-®¶ÂÁ#$ñ|΋wˆÄ›¡GÌËJÙjµpßäQÙalÈè)¼ê+w<ΈîÚß™þ ëçß½ï¿q•ºÇX–™?è±3OjÞªuÞ1™Ðs‘Õúô­’nŸŽÚe§7—w"Ë–AÄR·ý5YíHŒ)5T?ºœ¸ýJEÁ©p\÷1%ð5•_FÏ©(;ä25ïž]O q]¥ÚG$èÍ §×ë碳A1”=vŽ»©ôµA3”TöÃbT®@’·4Tæ]Š÷]ÃXåùÝÕ&—:®ÞÐBf"Î) ¡#7¯^ ÍÍjÒ`˜¸©‚J+Öù'f?Bi
-¬½¹¶äåÐNsY¡Lí5­Og±=<ãñúB¥²‰/Û¿ÉD tFXCqÐwš°ßw éFåÉ&Vë?»~F›‘鵟%}_}¿D´~¶ÃeÌú¬Y~²® ¢ï"³ÄÅ7ñòcd"@v Ùi­;—oʨýíÿcî¤g¿7–¹Jçù;
-¸—9g¢<mHq±ì§BNL™-³Ø~oÌydžm†Úù9g£wÛêö¡6»YD}Õ¦ ”«(¹ã$Bß"Š5¾|´GLž-³È~wôÙ\tœ/ “F˜r¿ FjÂ3Xíó3E4LÜB ï% z?ÐGK^Þ½˜² t¹gOÁ:t
-ƒ@Î]ä@ôÁ*Q©lèi gƒRBwØ/U¦Ápôöl”1UPÉ`cÐñëÏPò«n®yûôzzÄ.§jbÜpkbÖ±F±ÓÔM¶†º“_ŽÊb2¾ëý ñ~Œµ¤øzu= µ§Ó4̶…gä ´± y&r—=œèícXÛT5c·Ðt¤¦À€Úùw2"vXëÎ=µ÷¨=Šñòµ~ Ù;%F•ˆ¥"}GU‚–|(œ±fL‹ Ár2¬íƒKñ>kV( Mg0ff§ª¬óOÈBf¨œpÚ)y~ãÄÁmó%úŽï:pø$é«=àÄ*SžDTÀ¼ G½]–É÷ß•l“Ã9ÏèC¤O‚=¿™~p«™¦hšöŠï
-‡¦
-È/u†;À½­ACmbÊVwÌ»…R\}:…A §ðËé;y½#~"¢6¬î·O.'øö^!ÓeÓ„”V€WØåÇokQ©mÒñj’ŸËÞ^jÃ7\Ñ2ßzâÆsT®¯°š7²â½ÍáϺ¶•ŒX-¤´ÌÅ+ö<B ƒÈåpû+mñ^±›‰‘´‰àýeµ= ­‰ÉµŽI0}ûbýþ×`Ð&W1ذ?! ¡Ø—Ä®w/ïdÞi½Pšgb¯°¶Ða–¤ŽõÎH„öúcì_šuÌoÝJejïÆ)h¬ ›È'»Äšñ7DÓ µá“ z`á0†ñÄÞ[Mü1`ød~Å•ƒÓn>ˆHTöÈñ’g×R7’‹Ö{¿µÚJ†®NÜzI„ˆCEíÚwA[eÍ2¸ö­¯~'¨m…QJ#Ô~ Ôö[³\‘Â>Ö6ë³=tÏÜÅŽ^G/æ"o†NòãA®Æ¢œXÇ”ÈarN1-¸­xm£â«D7i§{Ú-–dïƘBk™³W̹»娸ÑÃÖJñÃËIAnfÚR¼¬qNéó³Äç™nJ¾_aH<ÝÌMzc}Öª‹qN{Å£5M@n±ý®¨3è8”Ó½èoeÀ!c¹^qNé=°Ybš&›CR1Getå=±çã+ÇCÜL4D`T%Vµá †UJ¼üäJým"
-=v˜Ä->Ïdsðñkȼ»ÚŽ}¨Møgͤ*.±ßy:™cÉ?ùòÏlc§ ÊêZm¥ÇA¤½B®{|•0i¬;‚uîþn*{ô’îxoá l·ƒ¾Ïùߘž¶|ã2ï ³´•î|ù2÷\œïz#u–­‰I¿j
-áW}šˆi‹LWN<ÈJ r3×–†SŽƒŽˆ¸–…;éEJ(D¢mZòüæÉˆv‹å)ÓYº"ônç"G¯¸ y謙`lMœ°‘Üš˜Ås…I“[¶Ö? îŠÕ„FÔæ‡â¼]–÷±2ª= ª½?: ¢2¶Bª]Õ^³B…Æ1nX/µ‰±'ïøK0";"vWÜKxE’g2‹4iã8%´­<"NÝ~QR‹Èë‹9»}êð.ÇeÊ4Ž^ÛŠ@?%ÔÖ7þ½WåÈÌз‘ÉN>àn­'+0­ç¶w¿ÑƒÚj[l I¹ü™¹ ®Ç6›Í—$2³¼¸G³ ÊëÛÃÐ (µ¥;gÆú¬]©,Ä>Š%=1”&ªn´žØö¡Õúíp­È³[§"v¬ÖéíN«{?ŒrzøtNA9ûx~ õ]°‡Ù ¾.Kzí4=WèûoL§OõwŽ¿ ÞûÕ–¾ ÷èc_‘‘“y¥u,ÝÃR›ìq—çß9ºÙHYpÊðî#Æô‘4!}8^ ]ŒQ!ù‡OÕ6}4©ù¦®‰Y™4Ò–W–Z‚_¯g› £“¯ ™A; ‘ö
-}ƒ¨wÏoeôaÉéâäõí<ÃO1øQy´‰PR%ÄðJï÷6á¹Â)6Ïl h¤=(D«Ã]WVpïbb ›y¯VÑßæ•Ñw„>ipdžlbÛñ‡—SBA›\®W›üÏç*l
-N½NLn£2Ìð¾*Ý:ux7Ùci’ÿ9pÄ4!5“­‡2rˆÉNT*›ôÏÊN Ød2¯þöŸGN£ª™ºGœ¹ûÆz¨{çbö9ƒJ,N°¶§RT·<EDTBÄ 1öÏ<²×q©"Ž¥±®t$ü”Ö$_yò¦gü,¼á¨ÏZCu1.Öx3ä¾XÒºv»£Îæä£³S=šïÕãÐ÷ÄAÄÆ›)¬¾jS hš¢³1Óu¤Ðž3{ê(–A¥¿Ž˜2[FÏvgøÉ›ÏYÆLËþôfF´¤ù,—ßþügè85C8¸’‡Æ¾ÄÄìvEÑãké}¹ì½ü²‹ìvEžÉAÆO‰Þ:-—äj¬ÎºXŸ¾øMJÇjû¡“·e ÃÚ–¼¸ z`½WM@÷¬á¡Úá§ÐYó÷ÙÉ=åi 8XÔ&É.¶ßs$ó.2 d>0FÊ_ÞɈð°š/Îm†Œ>"¬f´1 é22®—è#i•E.'mZ¥Fë¹k+]>‰w®ží.b©"޶èà pp%r—ýbÙÙ“Y|WˆuAªF›‚R®Ð—Šôw†¿ ˆñòü»çöé»B¬ ’бöŒ:{÷2‘èr8̲ÕBg_/߸³Œ÷ —w"ÓFcì¹pçLÔØcÙ{€ôf˜-¿bCP*\މʺ ®6lµ •X{`Ã&Á2tµQ©m2Ú ÜÖÑÕdtÙa a HÎ'»t_âåGoˆÖ‘Л¾ÁüÕ”`7óù½×L0¶ß¶ñŒ<sç%tâ@Co—<¿u2ÂÓ~I¯}EˆØè4ÐZÙìâ=„¶gêNØÜ—"l’Oæ³ÐjÛ”ì¯ËQN#—Š<¿}&Æ{¡š  ÅbÓØÆL‡ûkìK»JìÈŒˆÚ°mZüäÆÉûz{“Ï œ"*ËàŽÌm°AŽ3<ºrüÀ3MQ–%2¿Áq†“¸ÄÔ ×ùÆ_zPôM‘÷ï{Ù{ß®Ä×d¥£½¹¾üõý q^}-š€ÛšÝ¶wsÚ;ÇÑé}·ß
-ÐÒX_[SS[ߨÒ³ êjªªªkšáU`BSC}]]}CQ4äEA¹t+)â¢]÷}ß­¨È¢c)\ò€Æ„ oomnjhhhEÞPUô µaSMz‘“oÒµçp±£Èqeeu]#Üý^©©¡Ž©ùÜ4ÔUC¥ê›@Á½›ë«ÊÞ½yó®¬
-î”Ϩ«,}STô¦¤¢¶ä
-}]uEiÉ»Òòª:p™v˜ÒP[]U]C¿ qÑڪʊʪÚz
-P¡±¡¾¾¡‘Ytdá2O9ƒe ~·Ó+^¤¢¼¬¢²º¦ª´ ’\­7É µ'ðÈ,YpüÆËò†VPÕ Õeo
-_—TB`BMEéÛ·  _¡Tañ»òš†H§Úòâü§=yYTVÓØÒÚÒXSVôâñƒ¼GÏ Kkš[šÁ5‹ ž?yò,¿¨´ª¾©¤Ô”¿+SZY ï4¨­xWôªàUÑ;XT0¥¹¾¦²¬´´¬²/¼ Y¸oK+ëˆ@i×T€Ê«j[ˆ‚Åý®¨àå‹ü×ÅoÞ¼z|-5¸¿4fD~ÅÆô;•­à^•oóçݽ÷ð9¡C ¨É’×/ž<~
-tª†5®]^üòq^ÞÃgp¯×¦æÆšÒ×s®eg_½ó¨ ¤º¾¡¾ê]ÁÃÛ—/^¼|û!‘P®ù0çÚåË×n?xQ\^S__[ùöÕ³‡÷‰‚©& ¦´ðكܜܼg¯é)5åo_½|öìå«7 xikè…û‚<¥¥±¶âíë—ÏŸç•À-gAAâ.|–wçæÍ[¹yçÝ<Ó× ŒT{Ød~%ÃÍ3r_W5‚›U¾yv÷ê…ÌóÙ·˜Y~ùàöµ+×î<Ì µu[ø$çêÅ Y7î=/®¨©­.-xpíljBÂñÓWî¿|[QUñöŽËÉññÉ !ÿ]EeYѳœìŒ”„cɧ.Ý~üº¤¢¢´èÙÝë—ΟϾ™÷òme,©ü¼Ïdœ¹x¦Ô‚‚yWðøîÍk×nÞ}\𶢦¦ªä,ܬ+·§T—¾~zïöw`QÖ66ƒ¢+)xpãBFZê‰Óç³._ʈrë+N7#‡òª-‡Nß-¬lhj¨~ûìö…Ô£Gb3`–+«*Þ<ÏÍ>š’z:;÷в”裙©ÇŽ&¤_¼ý¤°¤ôm~Þåô˜ûýC¢S/Ý}Qô¦ðyîÅ”È _¿àè´ìû/ŠŠ ßÌLŒôõ 8tìôõùEEùnžO‹‰IH¿”󬸬²üí‹»Ùéñ‘á‘GO\Ê}VTZVRø4÷òÙ´ää´³—sŸ¾~û®øeÞµÌTXtY9O‹J+Êßæ?¸qþTÚ‰Ó—n?úö®>Šãûÿ(  ! A !ÉíÝíí‚‚[p Á!¸+^ŠK‹»»wwww/´ýÿß{³ Ð–=–lØÎ·Ÿß¯e¸ÙyóÞ›g3{ùÎÃ'aŽl[9wêø±ã§Ì˜»`Þ´1}ZFñuûÄõxtI½“Ö¼|ïé³G·Ïظ`ÒÈÁCš¶çpóÌa錉ã&L[´qß©+·îܺ|r÷š9“FøiÊ‚õ{Nœ¿xöȶe?ëÝ¥KÏ!“o9xêÌÉý›Nü±{§Î½†þ¼lë¡“§ŽîZ3{Lÿ®íÛué;z檇Ož<¼cÍ܉#5eá†}§/_CJ-ž:b@ß#¦,ܸÿä…‹çŽíÙ°hÚøÑ£ÇO[´~÷ÑÓgOܺbÖÄQ#Çü¼pÃÞ®\:shÛÊ9S'Lüe>¬Ðùk·n]={2¼Ï÷]ºõ0dø°Ý[Ö,!ú|¢Y’C,7ï?¸ÕçcûunÛþû'-Úrà¼mËâ)CèÑkÐØÙkv={þì±]«gŽêÓµS·þcf­Þ¾ÿàÞ-K§ êÔ´~½ÆL\´q×ÞëçëÛ¶aÝzM;ÿ8uɦ;·¬˜1¢{ËzÕ«×mÞmØ´e›wìØ´lÚÈÞ[·éÜoÌœu»ž:q`ó¢‰:·lÖ²c¿±s×î<ppï¯+fŽнS§îÆÌ\¾yמOâvú¾ÿ˜Ù«·8rxÏÆES‡÷ëÙ«ÿ¨_–nÞüôéc{7,ß¿CÓzµë6hÚªmÛ–1Q%¬Þ=¬o×äù«¶6wËыׯ_<ºuñøZE׬Ó¶ßøvîݵiñ¤š7jÒºÇpñî}{~]1}ø÷-£ë6ˆí1ü—ÅkÖ¯Z0i@»ú•"KU¨Û¦ÿ„y+V/›=æ‡ØZåJFVŠî0hÒ¼¥ËæOÒ¥Q•’á…#*Çt<eþÒ¥ó& îÒ´vTµº-zŒœ¹ê×Û×/œÐ·M½**×iÙsÔŒ¥k×­œ?yp·ѵjE·è6xÒÜ¥+–Î? SÓzuÄv‡×®Ý´aÅìqý;5oبEçãç®Þ²cÇ–U³ê[»|‰¢Å"ÊVªZµbdaK®?#ó?ö÷ìý[¾ãÈ©“‡¶-›Ü/¶f™âÅËÖŠýa̬e«VÌ›8°}tÕòª7ê4pœ¥+—ÏŸ“ˆ*S²LµÆûeúÔŸú¶©SºÕZ0²v›¾£§ü2iDÏÕ"òK¶°²õÚõ5aÂèþ”³„†Š…ÊEwè?z„‘}ÛEW,V8¢jãnÃ~^°lÉìq}[ÕŒ Ë_("ªi·!~™6iämëW*Y¤HÉJõÛô>~Òøá½[׫X²Déª ; ûˬ“†õˆ­S©L™ÊõZõ>eÎÂEs¦ ëÞ,ªD^Sh¨QÊ[ @^Kh÷¿Ô®ÈÓÆ/À…„×h;ø—å›wl߸dÊÀ65#ò‰bÞÕšw:aêäÑýÚÕ+ž?‘ru[õ:vÒ„Qý:4¨X$¯”·H…ú­»÷Ø·k‹š¥ò†„æ)U«å÷ýöéܤj1)wÎ@!éÚ-»ôìÙ%¶N™†~~þ†eë¶êÚ«gçµJ4‡„Z
-WŒé4ð§ ãGônU3"!wˆ¥H¥˜v=ûõïݱIõRÌ¡¡æ¥ª7nß½WŽMkD”DkaÈ÷ýØ»C£ªm¶‚UuøaÈÈ‘CûthX)\Ì•Õ××/[Ž€ÀœÙ3gLçò—oȼ۸=sH‘õ; ž<gÑÂY¶«SÒ–;‡¥hå†í{öíÓ ÇlÊ[ÈÕ°mמÝ;µ¨]¶ )WÎ\Æ¥ª5hÞ²iý*Å­AY¼½³ä¶EDÅ´ˆmV¯b1 s&ïlÁy#ªÔmذnÕˆ¼ÁY3º»gÌ’¯TTýF ëV.ž'8»Ÿ_¡`¹zD‡æ5"lAY}ýr •©Ù°Y³†µÊ‡[‚²eΜ-È^®FtØÚ‹ÙBrúò•¬Ý<¶e£še ‹¹säÃÊÔhÔª}‡ÖMj•-$ø{gpsKçî‘1£g·Ô©œ’þån!y¹é£ ùËE·ï3tÔ¨!½Z׉Ìäç•Ñ7§)¬l͘¦M¢«•ÊêŸÙ7k.1¬tTÝèúµ*•È’Ý'“O¶ÜRáRå+–+YÈèë‘.Gæ\Rx™JU*”,hÌáíî–ÎÓ/—¥P‰ÈÈ…,A~i\\ÒzdÉm-\²LéÍ™=Ó»{½Gk®ÌéÝ3eÉS´tùò‘Eóü}2¤K—ÁÇ?4OxÉÒ¥Šå7øyyfÊd +U¾RÅÒEó„úûzyùd±†—®T­Z•²Eó„dÍèæ’2eÊT..®.Î)’\<k»ï’¿tÍ&m:vlݨzÉ<A™3¤M›Þ+[Hž"‘åÊ•
-·æÎêåž>ƒwö©P±ˆEò›sùy¦K›ÎÃ7Gˆ˜'¯ÍœÝ;}jgçÔî¾9[‚ù,ÁÙ¼Ò¹¤rNãîãl²XLÁþ>î©S:9¥Jã‘9g¨(I¦ÜØéà$…E”)QH ôuOíâšÖÓ/Ð`±Ù,†
-/…$Ƨ¤vƒ§¤ƒIÃBÂk]ñµžÒá/°!¥kZwÏŒ^¬%).°3çÿ±kHR¸¦óòó
-
-ô'å¯cos÷ðÈ.34À$’§tIÖÍ--¬tò¤@L˜gJgY„€¾ð g×4iR»¤’à)R9;§JAN”’"¥3¶$G„?Ó$2dpgÚ‡]\œSáCS|O*çTrŸ_‹=’`WY–?¥ÁþfÞ8Åt3yeŒ#˜ým.4ÄÄß±Ç;¥H™æ€¦%M†`"D³Jæä”Â)y²¸†$°°"LÆÅõ‘[âÞâìlŸeÜSírùî)°ôïÿàÝk©%9óßËò§æˆQÐ5ujW;Á>z¿üx@ög,BŒä_$aÃcOÆŸ|gÿ½áƒ.¾å½_ÄMÀþ¸>‰>”\{Ã?Êò'çm§×û{ÿýöÇ'’ßž(®ç"$ÿâ}¡úHÆ>êò—·|ô‹O<å£_ü»,ÿÝĉ^lþþñØô¯RøîO½%Þð9ÚƒãÛ¿Ñ– ŠÔkWÏ%ª„‹X„Xþ\¡^Ûv1m\ʸ´w1ø•…ÿ±ú'ªž þ'kŠêì-\‚SˆÉ"ýLfCˆÕ,J~-°Ñb0 ÔfÌ&?h±…6™B¬’ZCˆ(˜-Ð"†X-³_4tŒ!f‘~f ‘£ g1ð"<Ì$IØd ‘L¢~ï±Á;©«"IFÍ!Q¤ßI!Fƒ‘Ãl€WðVƒd¥&£$²·ExŒ5
-û"ˆVû[ÍVh2 !£‘ æC=M¦£™f*…˜ŒVf‘Ì"›©`Á™šÄ›æb2ÃDÑÄzJ!p&ýL&[ˆY¨§ ž‹=MÖ ˆMfcˆÁ Ð$«h¤ž0iHN6¤.¼Ýh'ˆÕdA²U8%¿h2É=Í0=ÁÆÑl¦Ÿ™B$<K„¡YEz%ÒÛŒ?2ÃÜÞõ´|œ¿7 ò €ÖÐd ASÞFf”¬ØU
-1Û¬¬§5Dø˜§ÉŠo@’m6jl&$7¼Þh•`¢cˆÉ*±…F›€¿³ˆÀ‚Qî*Øðw°>‚‘æÄ’`L`‹Õb§‘ÅD5I°ò’ ±y V øCB²E6^‹€¬.‚Á
-?§®@j ç%Á$ ¢‰Îj’lô;à£Ü$áÊXaä‚-nÀV¬LVœ˜y…&M&­)PDv°ZC€¦ò€ Àïð“ äÉF¿R›o  Â`Ÿ¾Õ
-¤6à­¢Ùf§° -Ä&™hF>üÌfe³·JV›ŸÄÎj3ÄQ 8ÌF¯E¯Õ=ä z'ÐÃlƒ˜ä;ûÒ€ô „› ºÁÆ:J†n¤™q¥A²ÀãF&ü2'·˜æ ©1¹Q6À&‹u&´Dh‚Õ†`]AQ˜`6fDƒÅj–ß‚ã0Bl¢<« þÎ ¢i­fûšš & áo-´€¨®p=Ì(ó$¦¨™ °f\ ƒáã[áýf˜ŒñQrMVÖÄøØ `O|Åbgp¸p.üÌNJ˜1ôD)BµÁf&Í '“H‘Á@›€gÍVè òaeÞb3K&j’¬–¸®lVàhƒ â 4Ș%q–f
-Š›pa,ò€¦3[à­V”6ö;P
-fœ½×®¤$Tof+ð–Õ>W`#( 3ȇ`$5ˆLŽ;ŠÙ
-üc1Ù5†Á‹jµKÉzM¸á˜mÈî´Ë úC5r¬"ÈjÊdÅÕÁ’LF³}ÀV2!ˆ–ddêA`ºÀl³€8±µêHLËfR›Ìqü+ÀEH¬©ZyÕ±ÉÊ6-°HÛ£E°‰ ´h
-¢}æ   vÓuŠ(Ñ[eûÓ`Y¬ÄB ç´ƒcW£ÉÂ&j˜²Fh_ƒ½œô=W2#¹Q߈òP?AGÁ†¶ÑFO³"ÛAÚ`°sŠ6à6 ²‚
-p~°€ƒ4ãÐ`Ýmfœ»
- i$¡e‡]Q££ÜÐ@ˆÅ± F*ÐKÙ‚
-`=YHyX‘âL/´ᘶÇ&š¿¢U&4¡œØX“`µ 6½ÐjÅWX,ÌYÀ§‘
-ŸÃ´™î‡V í<¦ÝÑ9AÓG`6¡C-4±Q0ëøÞh01>"}ý,h´‡ÀúPÁ(XIùàìP¿×K&~4] Ø$6‘ɆD²!Š4KtÒ‚q;0‰LO
-"SvhÙ‹"SýDh°áþDËI&lÀ<lÕÉóÀnffäàä˜Ø™ãäÕFú?dÍŸŒ}èf2Ëû?´Áꃊ€m€;RÀ
-ž ´ˆr?``ê mE„·† -LëIðs`8?|¶‘”l‰>À~`°ƒQmF
-cmòŽ+¡oC^§•my¸“&A5ŽÒDÛìýJBv‚‹DÓCÞE%ë%HÌm4¡IÆ­hV1[ÙôŒÈ)Tù¸–D:Ì4À^¢,uà$0QÇ颌-Ød t±3.ªÅHŒ md‹"ºX¨GMö x´3ŽÈfA®ìÇá4J&Ód1H¬ŸÀÞJÔBýLÌÅÆÐÛ"õ30ŸŽžŽ"R…YxhS0ǘÏnj‘DFS?¶Ó†D
-hœ2ÏVí¥‰ ‹‰E)A:ì!‹Hé X
-#[9 l\MܧÑÁ
-ÅclYÀ·Iò4KŒ&óc&4 ÿc„…ø ýA ÜåQX‚ÁÚ%¯Æ„†¤Ñ$ÛëF1
-ø#+°e²²© åoÝ‘&gDÁDÿ
- E4QpÍè/Sn‹¤@
-Çbb3ĸI²7Úd~’LA b£h"u#ëj¤ˆ0µ€MÃXÁ@ÁZtôÀ9‰f æÉ¨É„’1/L¬A“í´8M»q‹î¥@Ó´°t´˜dùÇ 9þ¸çà†€M&Ù ì¥Ó(’Œþ+í7Hl‹ºÂ_’‰/°ÇUЖHè1ÉèQvÒ`¸*ø.ò­ r2ÍCNÿáãÐÒ¦&JmaLÏJ~)Ú›¤Að=&ÆäFÏ%‘ ×î÷Kl7&67¢‡]‡²z6"¢`ðµH””¬VŠ+ íI ƒšy}°™1CM‚ÕÄ|w *)‰ÉŸ•v%Ábc›-ºØÁ‚„|l¦ú5…FК™à¬Äl’™¥îpê,ò$ …e00Æ•ÓdÊ n¸&´u(' c(IL.&…r$;{ãË-qA QÖ(”?BNÍÁ¤ä…MŽ„ÍìÑ#3Û´qí`!)È„;Œ`fËIc…­Ò"IL¦-V¶kcÄÊ*XÙÏŒ¸ËRY,‡j’›Àø™ªg]m,êFšÌBásLƒI¤¤¦Ò?‘ŽvièRÙÅæèUþË¿NhX›vEšD·kÛ²^›Î~y ) ƒž«d ô ­Ø®M“–ü
-‹ŽnߢBl»zøÛ@¿Üð˼ð?æ¾)ÞÀÅ"?Ù¿Î'“áÔìX:»:œ§Îަı³£IqìëhZœú:˜Ç¾Ž¦Æ©¯ƒÉq¹¯Céqêëh‚;;œ"—©åX’œ:;š&—‡íX¢œÞìhª\¦¶CÉr™^¥ËiÆ&Ìeîr,eNLšËkìPÚÜ.Ž$Îeöp(uNïu4y.wv,}./±c tz³£)t™©K¢ËÃv,.Û±Dº¯J¥Ó°M¦Ó›M§ÛUˆ# u™Ø¥ÔeõãXR]ž±ciõ8ååHb]V@Ž¥Öå9+N®Û7U‡Òë2S;”`—U¦c)v¹³CIvyJ³“ÉåP¢]6KµËæ©cÉvêìhº rÇîÐÕá”;õu4éŽN»cg‡ïØÙáÔ;vv4ùŽ}N¿SgðØ×á<vv4 }NÃSgå‰xìæp*ž:;”Œ‡ž¦ã¡§C yìçXJz:˜”‡ž¦å¡§C‰yèçXj;:”œ‡Ž¦ç±§c zìéPŠU¿cIz|¥#izìçX¢{:–ªgcu$Y=K׳ž$ì±£c){6MG’ö쎤í‘KÜ3nw$uït,yÏÅ‘ô=ëéH‰#)|y–Š“ø8R‡Òøl)Iä3Æs$•Ï´É|6XÒùL‹8’Ðg=Ié³Y:’Ôg”u$­ÏØGybŸ‰¥©}¶•(Oî³):’Þ·/ˆò¿¬”§øÙ$Iò³i:æg³t$ÑÏXÀ‘T?£É~ywWœîG%éHÂÍBÇRþØÓ±¤?3bHû£ÝìP⟙ê¤þ™oàHòýÓÿä9Z
-㱑roJ,¡Ÿ ¢ù©'Fº4ü‡É+¨ú
-­G o²ÉMì”&LäFa£2 ¸ìhcÐÓ¨T†Z,Ìû‚]†U€S#¾ÔŒ±“‰e"LòÁÈ `*½Ë¨ }L:¹'Èù\ÊS6Ð`ϽÂÓäÐGSV‰òìјŽÀ,™;v*bøv5 ¥éq X)€Þ¼\€ì€«FMVvöÌÈBr›Eb$£¬2=Œ¢²Ô„‘#z©Éd'"fPÂÆz³P'ƒÙ¦•I®!²I”·52kËND
-¬a£HÃ5È.!= cŸ˜©ZD|WáÕÞc±& 4£@K
-è1¤·©KdðefV¤Km´ K´'у,T³!Èê_‡ìE-’d?ëh–0^Žm˜1d3¡-^bÁéçöUf)X„³‰•€Éy &S#º‘¬ÑDµaãB34RqjDÇ5òSÏÔRoXË@+‰ŽŸÁD¢õqcó/mÔPy ÁM00 À¤5ÒMTÔ†Û" jIäºai#zà†1³€&‚ššØ1”2ä‰</ P þÆB^/5¡÷‰¯”u”£‹XÉ(‘zÂg èƒ>`eAì•"Å Ì\¥ºså1¨‘j§Ø¤V .“Éïãyª%ñsôfL `rÝNuÌ ±ÞK03¢SÊ ©rñ=î¡&ùrIÖÔˆÑU¢§]bz‘X æLrÕ™LvÊõbìž*ìa¦GÃSì¥2E‡–ÉÎ<j¤ñÒ´{šÅ&ù}b¦_C9ÆùX#C1@´øP“â"˜ÐO6³¨2mD‘¬ÑŠ1ÒTfóPw3„ŠLZ"?õLMÕ—Q’·ŒËbضŧ›i£–êKÀ©*Ø×Ìø¡F
-µ‘:¢Ð˜Q`º†TV*ÑD0<E òU”lr£ÍÊbtVÑþ,±¹I.?"]ÂNŲ6Rj"«P¦‡YlD½D•ÏôN̤±&ùˆ 5k¤Òœ€Ä*½YÝîÇóÔTáhÐÀlšÄl'Öf•5ŽeD“Q.¸¦B2F#Uk›Ùi™ìLMY…Q­OzÒ‰ÅJI¡á;í÷›P#ê4sœêÇga)©%£Y~%zM¬…Ц¡‘Ó†TÀK U…£‚•橾ò2P È!Ö§*G›(W'˜ØÖ-™Ø©j´ÒÖmý„¥
-"¥0©z …©|C0³ó*x2ÑìÄšaòJA¡ái*ÀJ&³d“Û(΄Ų³´‹Mò[M´ß~4:µh'‡ÎþrË&mR’‘*Œ%¶Yʶš„1[,d°ˆµ`hß„…ÂFV±DÃÊf$šÑwK$ʵ1ÔFª@’äŠ^|V¨S+ÒÄ—Ê÷ɱF,1ÚXŒ™= ËEÔšä ±—bu5å3tX:‡ÕfÔ(È6åE{AÃ'¦ªšW$VVN…µ hsµ°·a™§Ñ,ך ø€d£R
-kPÅ`º jb¬€ãbÁx65ZM²8Rê˜=Íj±7al_*Èf5R ŠM>EO3aµ Ö˜E“üV¬ÕaMò=94:ûϘlãL¬†’ñÏT=…êˆ0[X®
-«~(–ׂµQZËÅM”mÆ&ª€1ó`#j‘]g¬²ØØ-t7F²Fææ°Q°ù€ß0 ˆ-¢ÒÐ"á-|Õô†Ë·Wae'Ø|T¸ÉÚ¬,޲Yù)5Ñq;¬#;%T0ù„…b”æwùDc$k¤#E"e‰L²§`£ÐDÁ<æ;˜Y‰:Y˜áŸ ÝßÛ\”92Ÿ+ 03 qѼ FÙ¸
-Êâ>DÁaš6VÐqf+“š7,’5²%@ž±Pg<ù@……È3*c&Ù2IŒ=Dv]âÇô< ,ÌHS F¬2´ÉL#Ó@“@ È4˜~ÿõÔZ:¯fb¥8XˆÞBn’¨
-­97Bëeáø¶ñ™ì¤ ok‚ø$>‡ÖüþÕ¡59þ‹Ðšë¿.´¦.ÇZsýW„Ö¤åøBkÆÿ*К¨ ­…ÃhM3އÖRò¹ÐšNŸ ­eåß¡5…88Ck¡ù'hMG µÜ|ZS…ƒÃqh-=Ÿ€Ö$áàpZKÏ' 5I88¾Z Ð_¡5=88¾Z Ð_¡5=88¾ZËÐК_
-­eèhM Ž/…Ö2ô´&Ç—Bkú
-.PjK‡ZÐJš¸@qèJ(ý ‡ZÐVš¸@qè ZË(½ ‡ŠàÅÁ¡"¸@qp¨.P*‚K‡ŠàÒÄÁ¡"¸4qp¨.M*‚ ‡ŠàÒÄÁ¡â_š¸@qè\š88ÔBüK(½BiâÅ¡WpâàP\ 88T(uÁŠƒCEpâàP\ 88T(ÁŠƒC]pâàP\š88Ô—&ÁŠƒCEpiâàP\ 88Ô—&ÁŠƒC-ħ4qâÐ7âYš¸@qèñ/M\ 8ô
-M¤‰ ‡^ÁŠƒCEpâàP\ 88T(ÁŠƒCEpâàP\ 88Ô—&ÁŠƒCEpiâàP \š88T(µ ‰4qâÐ%¸4qp¨.P*‚ ‡ŠàÅÁ¡.¸@qp¨.P*‚ ‡ŠÐD ¸Lqè\ 88T(¡•@q™âÐ4”&.Púƒ¶ÅeŠCgÐZž¸@qèZ Bkpp¨­… ¡5 88ÔÖ’„Кê@kI’¡588ÔÖ’$Ck2pp¨
-àó™ík³´¶Ðv8ô‡Ïä±øgõx@<“šƒã}hÍþêCkŠrüסµ¨ ­ÉÉÁ!ã˜3þåÂ1hH=EÐZVþZSˆƒC´–˜ÖäáàpZËͧ¡5U88¾ÿÌÕ\š88Ô—&uÁE‰ƒCu8, \Ž88þ\@888888t9"BëA$@$Jô§ã;£
-
-ΘÝ×#­³SRT>‰AÊ’$Ñïîž(q²Té|rÙJD5lݹÛ÷Û6«_£j•êõ[t0j¤±ƒ»6®Tؘ={@ˆ%_XxX~KpöLé€6¨{œR¤L™‚íî:$2MêŒ9¤ˆš±=ÿ4aÂØáztjÛ¦ý÷~š¶pùŠEÓG~߸R¸Í,æ ¬\½VÊ‘…L9½Ó¹¤L‘2•k·tniu»»ƒ¦I™.³!¼Z«¾cg-Y¹rÙ‚“~>lä¸i‹ÖnÛ³gÛêY#º5ªY"¢\õ†­:tîÛ rQ1ÀÛ=mš´îžÞ™ýü|¼ÜÓ¤bƶwÝø O.þÖ²{[°~ç¾{wlZ½tÁü…Ë×o?xòìÙã{ÖÌÞ­Eý:õš´ëõ㨟FêÖ¼Z11 s&/Ÿ¬Á‚ÉÅ+ ؉d4êfwO”8yj¯\£Ú½aÿ© —.œ9~pÏŽí;ö>uñú­›WNí^=cdŸ®ºþ0l⬅KLÝ»EµbRp``ˆ9_x‰’%Âó
-9}Ò»¤
-À|¾œ"•³ êžo3®;”g@¾Ê­‡ÎÛzòæãWo€ üþ;þÿŸþ ´yõìÑÝ[7nܼóàÉó—/Ÿ?¼qvÿ¦¥³§ý2sÁÊÍ»öïßµqá„>-«—
-+Z:*ºyëÖÍêV(lÌî™Æìž´é3xx¸§CˇçÛ²|À®IåžU,ݨÏÏk]¾ÿü·ß‘$ ÿG´yýâÙ“ÇŸ<# {ýüÁõ³‡vnZ·nã¶}ÇÎ^¸púàæ…c{ÇÖªZ3¦M÷þƒ÷éÔ¨R¡Ð,žéÜÒ{údñÏ‘#{f¯ô©S’UømÅ5ÀN‘Ö'$¼f§Ñ‹vž¹õäõÛ?þ|/CÄyûæ·×¯^½zöûÛ×Ïܼxêè¡CGO]¸vûîÝçmš7¶o§V­Ú÷<nÚ¬™“‡v)›/woïÌ9‚MÖ¼y,†€ÌHÒ=É¿!Ë”«gÎ<š˜¾áÈÕ‡/ß|@¤ ð;“°·¯Ÿ?º{ãêåËWoÞ}øôÙÓ‡·ÎØ0ÒðAƒ†Ÿ¹tÝÆõ˦íX§¤ ŸP)¬d¹Š"‹ØrgÚ$݃ Šk|–(g÷¬æˆèîVì»p÷Ùo¿ÿùaj Â4c¢×/`ðàáãg/_ÿöš)Ÿes¦Ï˜»lÃ΃Gn_1u@lµùmyÃKW‹nÖ²yLõÈ|Á~Ò8;»¤Iç‘ÑËëøFÂÕ=‰¾KœÜ9½Ÿ¡h-’¨ÛO_ÿ•4Œ:¾'`°¿¿xñònboeå³yý†-»Ÿ¾xéüÑm‹ÇõlV½\érÕ¶íÑЀmê–É—;³Gúô2ùùdøÆûAÕiù`ˆ/…«GVc±ZG.Ø~”Í'Hó‘€½yó†Dì?ìÊçðáãg.ß¼{÷æ…CçŒìÛ°A“¶=‡L˜6sÚ¸íë–²eõÍœ=Èh+V(ŸL–UÉëJ–
-~º¤÷Ée+ÝmÌâÿNš8“7²8åsåÚ­ûž>}xóìÞÕ3FõëÑý‡!f/[·qí¢)ÛÖŒ°‚C-K”¯Z½ZÅ’Áò‘ƒª.®©O.Ç|Ž|ÁÖ” °«ÛoÊʽçî|R >!_²ˆÙ•ÏÃÝóêÕ³×Nî\=wʸq“g-Û´ûÐáý¿.Ô ŸÂ…ÂKU©ß¼m‡v-êU,lÚ¤vMãæîé•ÉË3}9æÃ$,!„5`çN” ”ŠE5ë9fþæ#dØü+iþ"`våó”Ï›WOï^>¾{ãÊ¥KWmÜuäÌÅKçÿ
-†O˺QUj4hõý€á#‡õïܨR˜!{&OÏL™³åÊ‘%“;ì`lwO–<A¸ütó´–¨Þ¢×è9ëö½ùøå‡vÍgÑæ=åžÅã;WNÞ»k÷¾#g.ßbÊgî˜>™á3}Þ¹S‡umX¾€!gvÿ\)¡°‚yŒ~iR9%ÇÝ݅ }m´’0 ~zú‹%j´ê3vÞú½§¯=@¦QFš•Ï¿ÿöâɽ—ÏŸ={áÊ­ûIùì[?oâðA?Ÿ0kÙ†­Û6¯
-Ti=döæc×>
-c©K?åÿ
--^,¼
-¼†Ïp-N;vâ쥛w<
-Ö¨…÷ò9Dp-=|HÊöù§÷®ž>¸s˦-;œ¼ôÝ«'¶-žÐ¯CóÆÍÚv8jÂäIc‡ôŒ­aÉ‘1µl“(IŠ´™1½§®=›ꙄC™A®†5Hùün?züôÅë÷À€~‚Ûûü ƒûôî;tüŒE+׬^:{\ߨjá¡™Ó¥T®m€4n~¦RúNÛxìmN •2rP´Ðå‡7ï>zöò5mïû7.š>yâÔÙË6ìØèÀ® ÆõlTÆêŸÁY¹D!i2K6DÒ\”PTðßà}åóç{Ã'@˜7´½_?s`ëÚ+ÖlÆ¢„ËOí_?kH›ª3º&w€4Ni} %¢{MY{øÊïáS(Ÿ÷‡¿³š„û×Ï;°gÏ£X”pÿÎÕS;ÿÔ¹fáÜ™R;@šÄN©½ƒÃkw·|ß…{Jó¹Úâ¯Î;jŸ·®\8wîâUÜÄž=¾}~ïŠñÝj övˆ43/Õn8«y›€uÍÇøÀy'Ú<üàî;÷(/øòéÝ û–ëRËQ®Iîâ™#O…gl<z5áKÔGxÏyÚ€såÎr1æÓ;çv-Õ¡ZAGt s¡äß‹÷žké?}1P5c9&åÁ³xróÔÖ¹ƒc+æÁJáæè;ô»½leöš¸bïù;Úyݪ€ìw–üãíËG׎n˜Ö·q¤9Kz¥v Õ©¥Î%¤`¥f?LZ±çóJŽ4âò‚þñæÅƒËVMì^¯˜Á7mŠ$J™&©“«{æ <¥ê´ûqÚšýß<×¼ Íó{ö.Û¥Vx°w'e¤aÕX¾A¶’5cûPKq5VÂ…LšecÀ¬q„4ISºyÚJÖjõعë÷¹ñèÅ7­†ß‘æâ>0kê‚@¹)Ô5”Ên.^£UßqóÖï9uõÞWË\Æ?H×\9´vêJ[²+ô¡ð\Bï •šõ·`ã¾ÓWï>yùuòÝZ
-f@¶ytíøæÙ?ÆVÌ›ÓÃEDÉÇÊÔê<f ÕÕèŠiìlsv×’Ÿ:Õ òRä{S@" _åVCæüzâÆãâSPÄ`Úì_9áûºECÀêS¤‡“áËÈF?L]{èÊM³–_˜‚
-<„ÝË'öj\.o`¦´)“*rºñxXÞ
--L_wðÂ' ¨‚O`ìóîŃë¦ÿغZáÐÌÊ*ù䣨•[ ž…»“®˜†e^?¹}ñØî "%OEµ
-yrx(" èag÷,†ð¨VY½ï<FÕÍÅn >V×”³*,<¢Xw`ž21ßY´íäõGß^©ÚßA¦Ì­ G¶,Ó-º¤9«{*¤Ár¬Tx *¢NÇás6½ª«ÝÜuþð¯K&õ‹­¬¬N/Çru÷Íe+UH³é¨Ž¢5Ä3nœ=°yѤmkGXÀ®QP]C!‰tÞ9Lá•›ô³`ëñ¯zº;~öÞ£›g÷o˜?®o›Ú¥òäòqSÆÂó–Þ9Í…+Æt2mÕž3ú dQÎ6§MóÇþ[³¤MYË~ÞR,R¹Q—ÁS—n×EU¬®æÔÎe“úÆÖ(aÍå«,Œ…ÅÂÙMEª6ë>bÚò­‡/Üz¬+yzxõèæ9Ã;Ö-eË¥0ŒÅÎ[ªÜ´çO³×ì<vñÖÃçº)­aE±‡×O[µ°!‹Gj%a,º
-¨RÑÝFÍ]¿÷Ô•;žëǽd5|Hš–• æöM—*¹’›{Y…Dþʱ§­Ýwæúý'/KÀ‡çâOª2?¶yÎжÕ
-‡(ŒÕ°‹ÌƒÂjtµpÛ‰k÷ñ$ªn(;ÔÛ×OnÙ¹dl·úæl\Û`w¼‡×ê2véî³·ŸèŠ2rUÍ¥ƒë¦ hQ1_ f-•‘Æ+(¬f§Ÿ–îÆc ºÑ3ªS»qrÛÂQj UXLÍ®¿Ï_µíðùÛNéÇØ“†Í“Ûçö®œÔ3¦”9«¢0…øÜ³í{Ã4iyõäÎ…ýk¦öiRFRƲßV§ë˜%»ÎÜÒQÞ2."qãÌž“{c ¾»BÒ$I‘Æ+0¥–ƒfl<¢#§û½XÍ¡ÍóGw©WBY\˜¾Š…5–R º_®‡óaïð.V³xbß–U
-û¤ý|5Œ_ÍMæ”*g6cÑšFÌßvËbuBš¸XͦE´­UBT«A–qJé’6ƒONs±mé&>ý?ßÕ´® Þ¥‚X ¨™d)]Ý<¼³ù#ëv6GO¤y«Ó»eE±:¡›&ƒ~Ê pdõæ=Ç€« Ÿ9ùO7NíX:¡OËjÅ¥@%±šD‰“¦Lã™%H,P¼lTý–݇M_½÷¬~voæuÙ8kH»Z%¤
-o:ÂðžIh=hÚÊGÎ\ºqçÁÓ ùz,¥€ÍûÉ­SÛæk]9_€§’(‘&¨PµvÃæl<xîÚ݇O_¼z£#ʰJµs»—Ò¹9EwÖÈ÷øàuÔ_¼ý/Ô_„Ï~nÎGÉm ¨†=ümåšöýyõ¾s70éEȹ¼{aßÊ Š¯‘½¯ÓyÔ‚_]¹GµXú! ݳujKÆt­S4Ô'­Â*€Ô^ù*4ë3yù®Ó×¾pà‹> ì ·/Ú0kHÛ¨B k)DÃ&‹P´F»!3ÖÀzaÝlÜvÊ\<òë¢q=•µåPXKñ½
-àzÏßt肎NÚC5S~h\6O@¦´)“)»Ÿ¾Lí/EÖï2rÎúýgo¢É§#Ò
-/⳪päÂx@‚¾ã])Ⱦunïª)}›a5–¢ÕäøgÁjxñÈ™ÛOô£hxr\.ú©kÝFe'ç䳨ù«´6è‹4üþúÙ½Kx<¬Sr_ ;péo-׬ÿ´õ‡uu‰Á~ò}ѨÕ )½QMòÕí:FgWþ¤ ù¼,¶ŽÒ»±ðÀešL¹ò㇆1"¡3¶ÁXÖ3 š;p£ òe3GÔëlCE|zÚ¢ð,*Þ—°llWür‚BÒ`ÎÛ'w¡ª­ÏÚ„ÿÔ‘Daß«g÷®sèF5òðsù¦}^{貞êå뱮ܹ|ÒM”Þ¨Æ.J¤)פÏÔ5/Ý×iX}ãµS»WOû±m …7ªÉç
-Óg.T¥å€é°}ë‰k¨Š¿ž>sX§z‘Š(:Wè•S*U¯óÈù¿×O ß»*¾ sFv)—ÏA)¼•Ë…ME«·fßþüÖ>^ó°Wñ-׫IÅ‚!~
-?ÌÇ-†ÂUZô™¸dû‰«tdר«øfn[½¨1+ÈRÂ4)Ózå¯Ð¤ç¸…¿½tWO·ÄUñõi®€RÿÄhM†ìbÉú]GÍÛ|øâÇ:ú2À{U|1‘–ì.
--ò·Þ[ š¾îÀùÛuuËû»*¾F‘J¿ €TŠ´¾¡Eët³xÇ©ô1GØ«øfl^ÞêŸA±¹÷îþ{ÌÍéGÑ pó¾uzÇ‚ám•¯‘ÆT2¦÷”5‡.ß×Q‰áÏ?~{~¿<'_Ö­èÃ>ßá.…âõ{LZuàÒ}].LO¾¯Ú;&˜ÙMÑZèkºÞÁáµ:Ásºú©!`DâŃ«G6Lë׸´˜Uá÷ÕX>!•6Cçm=uó‰^ê
-°•Òè+V#Ò½tbÏúycz6)ÏnKPäAáQ¨Ð°*±¦­£Ý['¤‘¢ž?¼}å¬Ñ½ZD²(²†éÞ°ô¾AyËDw5oË1Ý]vîàæ%S‡vkULÌ¡¨„$^Þ˜Î'— ?pù˪=goé& Å‚X—oY4q@‡˜JEÄ
-Hd
-°–¬Ývàä¥Û_¹ÿL/uæìÚ°Ó;—OЮnÙBÆÞé8ÒÆÝ\¼VÛS–n;z ¯¥ÖÓÄ]6wD—è²B³y¹9+ûê–cå.T¥e¿ÉË€2·ëÇ6lPëjEŒÙ2Šb5TŽ•U,Õ ûØÅ[]º£#Ê|pmX¡àÌé•…ß+Çš¹áÐÅ;ºú¾¥ýÚ0VÄÇ2 Jݧ\…°æ˱ôß“¯ [<¦k½¦¬J|ìÌeXÍÎc–í9æú¡Ì»kÃ~éß¼BÞ
-/Øox¯Þa$~྾ ðî,ê¬!íª³kY]FŸLè4zñÎ3·ôúü?ûYÔ³{VNîC'ß•°ýn» ¶ëïò{b›®Øº`tç:Å¿tJnëÆ;Õrä©ÐýÊ«:»üþÿâ>þy`í/ý›•Ï“CÉ-…˜JŸÅÝ}‚ýs]ц…ø®ÿuÞðöÕèæ°Ïw.)ˆ•»PTÛ¡s¶××¹¹ÿ#'
-]o:Ýݹv‘P
-š>iœ\=s`ÁÑ”Õ.Þ{þ›žHC”yñøÎ壿.Õ¹vÑP_ùö±læˆúÝèÛ5OõâY"°ìóõóG·/ŸÜ½zúà6Õ‚¤Zð.ói<ýňº]F/ÚqúÖ……í!¾ Çv­™=º{£rl÷þLÊ$Jœ4…«;cÅ|?–Î/ëˆ4xäýùÃçm]1cTÏæQEŒYÑUøì »\ÒûJÅ«·ê?uÕÞózúÐyPo?´eñÔ!ÝšF·äÌôÙŸÚ`a,_ Lµæ½ÆÌß|D_÷H—p娶%“vŒ©TÄèóùõXrËQ£e¯Ÿæ¬Ûwöæc=mÞý¼s~ÿšéƒ;F—+dÊéýùÎÉa,K‰š­úŒ›·~ïéktÚRO¤¡+ Æ÷l\±àŸ)Ýç@c…GÅö›¸pÓ3×îëé´¥LšÓÛŽî\7ôŒ›³‚¯&`-–¿µl£žãm9|þ…$ôÃ4$P·Ïì\4ºSí¢Bw’¦ÏþjÆj
-Uaã¡ ·=­+ʰ;ÞÏïY6®[]pºÓ+©TK”Ø)OHÑºÝÆ-Û}öæ£zŠï!ä[
-×L‘ëj”亓8¥õ5”ˆî5eÍÁK÷ôuÕ‚E=¾y;Šª¤®F&Mƒ^SÖbß)ÔeèÞ0Ôà †·©’?ÀSI] Th±zÝ'®"Ÿ[?Æ…±PêP­`.EõqŸÒ½x×ÙÛº¹tÙô»©¾qÁˆöÆÅ3g¾J±ƒgo>®£S> t5iÙ8ëÇVÊ¿ÐBŸí.Ýè‡)kt'QŒ2÷®žØ±tBφ¥~]¨ôYŒ%êÉQ,9Ýl{ʜܵòçA­«…‡*»
-¢úK‘ÑÝFÏß|øÝÿ¤yb\sbËœÁ­« òN›RÁ}jôµ#ïÜaÕÚ ž¹þÀù[:»ÿÉá[0²Cpeæïβt¿l÷9X£õ|T„|ëòʉ=cJ‰ÙÝÅ>™ •iÚîêÖÛÍXÆzùðê±M³·ªR W¦4Šì½÷‡áÇÃtÆ’wïqÝê•0ú)ñd®)Û´ÿô G®>Ô͵#q
-ÂæôêÉKǶ¯˜6¬KLùÁ
-/2—£æþÖòÍÍÚrâ¦~*Õþdÿ<±cÅσ;5(_04KWewÖÄ‘¦Å Ù¿žÔið\ÂísûÖÎÚ©A¹‚¡ì„˜ÊÈ_ƒÊW¹õ°ùÛÏè¨*–AaõØ+2dóL£ôCŽì¦ØÜ…kvƒ7³à­g÷E=ËÍs†u¨]BÌá…W¼+§÷®^žºöðÌ]~Güñm»švÒÌÒ¶z!K…—cýÏþ 1[…–ƒç ªyõö÷ßß¾ùí·×¯{óö›Žj1:±uþˆŽµ° K…’†ÝU½ãè%»ñ¨·oß¼~ùüéÓ§Ï^¼~w`ì¯?ã² =b"%…7@ý•x‡­Û}Òꃗ¼ø óôѽ;·ïÜ{(ÀD ”}kÔa§
-o˜ùc+ §QvÔÿäÂ#!"懟×½öðÅ«WÏݽ~éÜÙs—®ß•‹×@÷¼|kʇî £~__ñWiR¤Íl,Ù°ï´Ç®=xöü郛Oܳ{Ï¡“—0ŠÎtÏëW¯@ù|cGUY™ù‘ 3*ÿŠci×¾|÷áû×ÎܶnŲëwÁÜËooÞ¼~ñìÉã'OŸ¿wÀù›ØÝÙaÔÓ;ŽÄš#/ÅÊÍV®¶bÏ™«7¯_<¾{ýÂiÇOžµ|ë‘KwŸ¼xõâéÃ{·oÞºsÿ±ý;IJòIèÚGþŠã^ühBxp&eû_\¹Zõ#æm:pòÌɃÛVÌøi`¯}†MYºíø•{Ÿ î9{úÌù+·Ùe
-x¯<ìcoÞ$tíC_q´à2ØÛÒ$sñÈ‘§|Ó&.Ú°}ç¶u 'îÛ¨aóNƒ¦®Øuêêí;7/:´gç®ýÇÎߤ+8€0¿½~ùâÅ‹W¯ßØ%,ÚÏôe€—oݵä§Î5 çv€k¾Kš*ŸP´f›f/Z<Úè>m£«–-[9º~èüÔ…‹gïܰréòµÛ»ùôÍÛ7¯ž?yôàÁÃÇO_¾~wOPFWª½|r÷ò°‡[+­Š•I“Ä)µWNkd6½‡Œþixÿ.ÍjD†åÉ[¸\t—‘s7ì9thÏæe³&O˜4cÉæCî<yùúõ‹'n_¿zåêÍ»@Â`ÛBFzC–`ö0ù¼åËÇ·/Ыai ~ñHáæM¥Gé|sç-U£q›ŽÚ5«[¡ˆ5$0×ÿ·wàvUÕ¾¿—NÂ!” %œ
-Ñ»Ükak3fì*ú'ö¯>~ÜrÜ0Rgo½ë´ÜŸwo;e‹)Ûï}øÉgÿçu¿ø¯;n¹ñšË.ùö¥W]Û YLéú£éÏ?'Ýâ÷¿õ…pj¢·æ©ù7÷švÔ.¿`+¬8vÅå—mZפ_O†í¶Ú,ßh ÞxêÞGœzöÅßûÁ5W|ûü/þsgžwÉo}à©—^3¥ë·¦[<òÐÃ>þôó/½üâÓÞÒÀߢKóo1û?!ø`×eëbZ×¢2l¬µA‚ÛbýµÖ˜°æÕ¶ï;òä/žûµóÏ:ãäsôGOýòE×ÞöàS/¼lJ×£÷ßy«éwÝÿÈãO>ñð]×]tú‘ïy+½P÷/>~ÁþÝA Ëã\kÍ «¬´âŠ+OxûÆÛísèGN<å¤uÈ~ûì³ÿáŸ8ó¢ÞþÀcOþæÑûnÿɵW^vÙU×Þtë]÷ÞsÇM—õìÂ-0|ÿ’½vP¿uÔ²ÁmÑ7z™1ãÖØ žºÇ~rÐŒ=wžºÕÖÛï9ëø3¿}í-wÝ{÷í?¹æ;_ûÊ—¾tö×.¾ê‡7ÜpíwÏÿÔ콦lÔÃ÷¯ú×£ué}Çm!ÃÆ’K,¹´I>oÏ·˜ºãN;¼krFI½õ‡|ü‹ß¼êÇ7\÷ýK/øâ'ÿð‡?vÊgÿÏ‹.úúW>uÌ~C¦^þ÷¸Oóøëu[Ø?Èk1–U‘l¸Îšýk®Ÿm¹û!Ç~Î7.úæùgžú¡áý§M›qÈQÇò3ŸýÔ'fï·ãf®þÖP¡ZýõêxtúVxÛêk®=i­þÕÞ6nìJ«­“NÙíÀ£OüôgO;ùÃÃûîºíV[MÝiÏýg}àÈÃÜkûÍ'Žk‡á{«üuÝ‚.»ÂØ•V·ârË.³Ì²+¬2)ÙbÇ}Þø‡¼ï»·Ù4‹6JêÉSwÞmwï°e=0‘
-Æþ·ø›Ëe:zL³Ë,m§ Câ2}Ëö9Ê·5îó-ÿGézÏ¥X$<öƈå»°G¸ðþâ¹»~áòýzaø›ÇRüûõÿÓÿ)þÿß¿Æß¤I[ºÿ–ÓgOï{Ï»ú&MžšO³ßeú‘³gÑ·CßQ}QÿŽöþ¿Xÿ{Ïô>þÑIï9¶Ï(»ô%u1•yÒŸå`åqÿ°ÑÒÁ,.ŒT FEš÷'u<UiZƃuR•Fˆ㺲Ve6qÜ?£/©*ûui´rК&ýöËÁ,ËhWeZÅ~^ê7ù`™{³d°L"Hé`]•i?”¬¬r£DƒI×ý‰µO’¬¥ª‹œvöå2.* Êú¶vÖgÅý)í ûWcÌÌ*}Q§4²¥imªh0/2›Z‘ÖEF7Å`•ÚL’"̪<Ó‹8óvÉ =Ñ «¨²Þ‹Èþcî”4Ï­§¼Œ³<W»8®5¹ÜúªãDkR&¹µ3J^i”©ýœä,WÁ8‹Á”¾iW V¥­‰­i”Æ6·¼ö°%£Ì¿Vqm”ÚV2©›VujËdûeÓ(ô«¢°~jšfúX•åPlØÖVÍìd,Jm›b n¿²­(Ø&£ÔYžjØQb›“Ö¶QÞL.b*Y”X_üÈÚÇ6”,Jí³u­ÏÕe\%¬Š(ÓZF6ͺ0š}—cb‹[çi,B^6Ê"¶µ‰ùI=˜×Y&WV•ý*Nó„ý¶q'‰“,Žó,Õ×ò²ä'œåfIrûF–Ø#›7]×EU%²ãj?âDiÊoR;?¹šÙ™Š¦–ØzçQ¦Ù×­]jÿÉŽFÍÓÒV/S«¢°Í–E>þ„ÃAשíL̶q€+»A¶óƒqšTúXdßMmÙ2»/1]—ƒG#Ëlζº¢Ø§ýYÎÎ&Z£Ùƒf»•hH¶76K£äƒyÅæ‘Ø,lðEœ¤áÚÄqL«Ê~œÙÌìàÛøQ">ÂEŠs(6Ç´H›via‹œi¹’D}çU&‚VæP1F»d¶–>µd°¨ìDe¶YÄ:Úe´µ´u´ÿTÅQ®Ëg¶ìvçíŒØ•¢]à%w×΄F™$‰SØ[ ’3–ÙEÊ3oÅɈíkv“ì0ùLÄ/2»%u©~ŒÔ¥QìŽäqZ†¯åEä4Ýx;Uƒ6G› endstream endobj 726 0 obj <</Length 16291>>stream
-KmÓŽì
-ÛHË’-0ŽiÛ~cפ(‹¦YTÛ5Í“Ì&Wge¦P8^5ì¼ò5Ì^¥= v
-ÑʈÃķ„yæv™êkë\Æ6º<µDIÓ®ŽìÐå)?ç€Ù÷{žÓ-â°-µ-xžÚÎý@Û8mÄFË8¬Š±6ñ( Æ÷ªÊ.[žev mûhOƒhQk°½¶­¶õÍêæÝ³],™qnãÌ2gl—ÔÖÜn]\hzvÙ«„eþ
-þ`}qHÈJI‚v9y $v–hg]ð)_<Æi׫òå´žJ¤Sûpë5N%^:£/ãNp~s$ÎÚ†€˜—Åa˜m%måÒL”pñÎÞhv"kÉk»Ÿ×HCˆ‚vbñ#{ãªÚŽÏ”>„8­®_ƱD¶(ÎÃ0^³aD»¸6`ß³3moa{b»ÅD>8-Ke£ÊR;ÝvÊÔ·˜¿µ³7E¢^n«¨hÇ~×nd» )Î8R¥°Oëkv¤‹‚Ç £¶W5³#"ØÐ.á•3ȹ¸ŸIø&ª©]æZ‹‰P¶*%¿Êta‘EʰíŒÇHm ÛtoVùã³­¹û™=Mzûig[›KF[0ÁמÔþ€Œ˜•OØö-•L(1š%‡Û› bûkWŸI³fHËv¼+¤_Ô»Ebí¤iK•‰="$<p´2&RÅ©Óè2+j—+¤ÔBqX(Qí;€
-a´ð.”šÝ\;pÖ»jžÐL:Gìka¿Ëd3hø¹½œÆg05 JiÞ1 –×'à µÓ ïZäsC]Dàù‹ë0$-ç‘õÇÞ„À’¡˜½Ú»Àú¡½åZì(LÑŸ±ù oc2ã=Nàüþ±D[iú£ uŒ(rµŠm_¦QËšf§ÜhbaYŒüÇ›ck›.³N¥Ïa¨A
-¾(z£ `k€"“ž"ú¦]^2„'0Iö J‚Æž#ÉçY»ÑÍŸF›¢Ûߢ”]@“‚w§è3¦Kh}%×!àEvAÂjJ/@Ä‹b,qö²¬¢¡ä2cvRëZÖÆ”—Ɔi7Bï%B¦¸í¤ §Ø*_“xÝÞ*ýÏÙÉF)–Å7ŠÂCÅR\!ùÒQ…Q Ëi%¾é¼›…[˜eÈLU5]‹R`Á)
-?üX¥“B†.iTI‡5pÆÊÈ žEæ¼—žMŸqÞT D{`_‹ÐÀ0ë¦áW:î.ú—N±î+QŠD)+g™i69–=È’ŽRcÅ#j¿#&ãûÍ +ï2̓'Áì!–ý¨l/Íç¡4K\ïK3»$l6G[óBŠÒß Sî}íûÚy4&¿(øYÅÄC0
- î)fŠ<W;®ìÔ)¦GYõ27˜šÆk3á4²r @É—ôŒ á¡Õâmö€¦ØÓ–Å7sT4»´v{1â(&ù$רLJ´Ód“2•‹vI0ýe¹¿ZôqÀS¼ U¸`w®]óÆêÖZRÌ€qŒ £Çiî3Ö»mËíèŸ&½æ’í3,ÕèŸQ&+0lR‡Q«ÉÅ€O昈ù\sšy‘5ÈÊ¥oÆzÞL¸ÃÙ(·Pš*“q>´u®—ÁÍ´ùRn )JA—UO%*H»ŒaÆ~P"^œBƒô§$
-jJj/ò4¬FÓ†`bªtUlóT+P»%E…OQDLZÏÈó m§¦àÙ%Ào á‚v²–ãl™Šã,}'…»tŒ’É–%6â#w®ŽW&EFgPy»O&KÙ]Sr2¤hûœ¸Uåë¤ÝX¶J4wqRÔî„k˜ºÑ† {¿Ìƒp„TÎce´LQnl,¢H ÇdD.hrëpÙõ@ж|î
-É;÷‡ÿÆûI—EʆáI#X 6)<GväedÓ©$²1ÑZì+F3ÖÄÓ¨ðoóñ{œc……bÒWÙXQ0DA‹q«qŠci&ëöÙo¢ZŒPzšÌvfcñ¸:xÎì|K‚¡Pþ&Îw!ƒGêŽÛ£e0|qBdÕ4±‰ËòÆÚ a6ʵ&¨‘‰Ì l§ÍNœJ†2À Üjc’@¦Ï!PËõ…u‹C+ï›LK<òZ¤4<o(;i䳕`„µ­’~šÊ;Áº#ÈcMåäÝ0AU/`ŠÅer£`ª§(ðÝTzCãèß´×<妋â¼{Ÿ·|–…1G(¾Oꉋ--1<i™Km2•â’¥Hv~»t1¢`*y¿Æ‡ìŒ¾úvë«û×[¿ÿ={Ø?Mš¶Ñä#foyÐŒÙvèô#ŽíߨHë Ø¡HìXÇë÷o´ëì#:ôÀþõÞùÎÉ3f5¼Ëa³§óÛõû7´_nbÿ×áû•xÿ¾"ô<iÚ¼œÁPÛ¸ƒ­];‡0 Û¹„­e§°5ké¦e;ǰµlé¦eçph7ÿîa¶sû$[¸ˆY×VNbŸäü»‰½] G1G®«˜¶róÁVîb¾ØÆaì—ªËØ[οӘvíÜÆ´lã8¦];×±±ó˜–íÜÇÞ²…ÎÚÊ…LÃVNdoØÆÌ³ÓΑì-Û¸’}´mœÉ|³;™–­Ê>Íùt)û8Û8•iÙÊ­ìòCÇò¤im]Ë>ØÎeÿd÷2-Û9˜iÙÎÅLË6Nfk×ÒÍl-Û9šiØÊÕl [:›­eKw3-[9œ­aK—³µlét¦e+·³5léx¶–-]ÏÖ²óyÒ´¶îgkÙÒMËv.hkÙÒ m-[¹¡­]KG4-[¹¢iØÎm-Û¹£­a+‡4íÚ¹¤­e;§´5lé–¶–-Ó“¦µuMÓ²•sÚ¶sOóÅvjÿäü»¨i×ÂIM³VnjfØÎQí»ÑÆUMËvÎjŸfwµ³…ÚƒÞÊeÍÛ9­ýnÍŸÛÚw£…ãšµr]Ó°•󚆭Ü×>Ô6lø\;6ßláÄæƒmÜØ´kåÈö¶qeóx´rfóÉvîl>ÙΡí-Û¸´iÙÊ©ík·¶¯lÇ6¢@+×6Ÿlçܦe+÷¶‹--Üá‹óïâ¦a+'7Cm忦a G·ocW7-Û9»iÙÎÝÀÛÎáÝÆåíú@§7H+·7JO;Ç7ŠV+×7Zaç7jh;÷7-[9À]gnãGOoçÇ4ÐÎ Ž!£•#œ†­\áØ\Ú8Õ§…;ËR+‡8 ۹ı‚µrŠc±kãÇBØÊ1îæÌ®q·f¶qŽso ÷ø¤i‡öÍÓ)n¤#¦ÿøä©ý“š}X¿‡Hô¡™]?¹¼âýëMÞÿ°ýfN›<µž¶ã~GÎ<âƒ3÷Ÿ¶ÝÌc§ùŽtçù|ºÙcëõÐÃí/KyØ7š<5Žß=ó˜Ù6¤¨£­˜9s·C÷?Ì~¯›><sê¡ûÏ<Æþ½¤÷ÃŽ8¶ù÷Múæ=CÇøST½N·ÿÿ£ìqÿäÃ=XC Þ‚=Q±â¶sÆ·KûÉöäÉ[ib:ñäXå‚åâV|œÌë<Çz|‡ e‚e"=/ƒ× E× å×ÒÐÈÞ†úø;Óž´æõÊä\a%ò¸‚àÑ¢D’Ê)ÍÌìíX UžmÖ¢-¨ÉµÛ7c[™»kÙ-f—¸\, &F.Ä /ש½Žr°Ë™oqƒ™»h§«‰cJÖf4LÉœŠ" ziêœo˜·Ê qÛõægò/§îΈ1ž#‘Ë™æ!rv ‚Àc&•!G};¿1» h­9´òc³‹òIÚº¡"/`gˆíÒØN~R¹7V&k‹âŒ¥D.¤
-=l²Ç`,
-ˆ$>ŠJ[Ê>…”L–sNíÍà2­Ž7¢®ŒR¸jW°VÊèR§nó6Ž#À³\ð¹ƒLr‰xäŒÜx54þ&gªg3{]!¨ ÍjOZˆL ¾#æb
-¨R›˜­·¤Œròª`û/j(Øý‘ °ºåÐ%žíÊ“0”‘ƒ=eºy$¾Ozu €ãâÅÂRXE~Ã0VƒÀÏ‘É\fƒµ Æ»ªL
-GWa>•‹ Œ10„‘s[`ZKl²MW@Lj,pд]¾Îb;/IÀt¸Î!`Ž`&™•Òu!£BRЉ!t)ú€3RãüÅ£ d"¸£·q zð5DsBŠ
-Å‚"0-Ø”¾‘´!uoâoí0y<²¼rn Æ«/ìgƒ
-³]=Z9»ãæ Ž0¬Ôµ‚käeÀð&ŠH<@§Âဟ'ÇÃ{Ò¤+´Û§€Þ
-â’3'²áp¡%]¡( q* }À}Ìè3Å#¼v?kÁK³Â¡Ì/JACp¥vE€…ÍèÛõos“Š‹(}½ûdéîEbzˆ
-þǤ“ÔyŸ2Þ+¸GË!S‚ÍÅðæÚ®\sZ>°Êb²Š$È- 8Xeˆ½Ë=þÍÖ?Þ’jÕå?”@˜>Ì“ùifL)IÒ¼ü=«Ž©'·g¶úØÑ˜
- ŠŠ€-!Ýáëž„,#
-íX8ä…XœHø.^»8qåGf×\
-Ü$2 ï¡ôF ÿ…ëä£Â5 ?Ø_²Êÿ“dFa4Ý[èXë$$0Àz•„²K‚t‰ KÆ ´UÖ 6'ò
-ø¢€ÿBš'¨*(/àªänÄ{^Õ –í¤½gxVz*
-¡ém@<à±,¾“4pIX J•qBã JÈ{h
-ÙðK’Ààf ŸøòLá4“áM!¼²Ti‡í¤q@.òzÂvdõÌ*ʹÉ/‰pÛ
-YY•Îxp*È®Id4oÈ8Bâä>q¾“éY%ȶ.)Á넼cŒ:cp2oGèû8ÌÚ¿¾²G÷•ȸÒ×òpé‡ûª&h5W~ ;#ˆi±@O+cC–|¹Äÿ H¥ø=i™;]J"²K·ˆÄ
-ŠB*¾"ÃPr/Ð. e_ð9ÄÊ0OÛªä¿EÅ& Rè€*b½ôå¦AQ<%žïĆk”F+;`F60|A¼·``ú€°Üý;2†Ur þv¿"ì³Ð«¤Ä¸D•
-í„yGÔ
-èbzòõÌè+ªmLïžG€mŒ4ªÜ¯z!ý9ñÐü8ÖT”1MqQ!@‚üiÿ¥
-.z¬xü¨ ˜bïr|ÇX>”ö‰vÊ—…vaotæÃV ¡ž•Q‡ §R
-qg¾®ó”á„¥AÌË09÷KÆÊ+k dú¡#Å–3»„È/:JrŒé„ø¦™'ˆÉgŒ*‚;t¢à"Šs¿¸çRWTehƒ"…ë•ñÊ)JÊ뺷 9žP¯³Z¿r4à€”¤,ÄcaØ—€lo›Æ™û’C« *î¡dn¦èœBIÚµ²hìDÓaYR”{.?@.7x•hÆò9â6‰ÏO´Ý.b˜ˆÛ/ >.ˆ ”Å„WÁPçID’8×n~$•@Ç7 ;ÜPv׉R ‰dÜ*ôR1Â83´½Ò-Á¬j½#f’÷/×!·ãЏ
-ž ‚¶£ ?^’3˜Æ¨½""TÂM’ ¹KËø£t§
-Œ©D×byµõÕ^Y§u¼‡5~ñ‚(4Ùˆ³Âa½¶¤S”sÏcI_¼/±r,å€wIø£l\Ø–ŠÂx1ä•ò[Tn+³v<G1¦>⃈X-1cÆQÈ‹ªU¢p(«ŸD3^K×yŠ _”ܯ,x±”±£„7£0?E»O±—hyîÆfÐ}üH¡­PPUD-­ˆÜáC«îC«R"fàj“µ›ÃMfÛïàñF3–¼€¹W–,Ùðº’#©¤4yîO@I«²ç€•«ôà”z¼
-·Ë+© bM왺@²äá~ÕªÄ. åžâOÙ<0
-”h-0´q7‰ÃȾ¡„ð•8f‡ý´{d+‡3/<† /öµÒ³Rå²<*†$»RÛbc#¾éO¨nQÐÿ6=-…LØ:*¥Ÿ”NK‘,…{м™±×Rª¡G-`dkÁ8$îiÍ-[‚7!'P’Õ%ëž,ÈܤBá[÷„Dµðç˜ERO»¨ÐÅa»’‰ßÎm¨‡†á5$¹Ót¤nËÚ`°
-B e®9¤9Ž›‘´Yoˆv@ëõR,-È,åèî¡e1ëI”Ö¸ÎÌž§îÊ ñ¾¬èù ‹¬L~:”æk3úzh™ç¬húÉ+ w¿ÕP`|͈:¿êΤégÄÜ@št©üî`íÒªJÁÌÝî•)¯{ÑPºîü¦3•¦›¡ùVï|íôËàºÉ•÷ŽÇ®ùT‡Ò3ßóhú1³9óe< rO:Ž€“Âaj™ i¨‡TËP©Óp¤NÃVwæå!g
-ˆ1õ¥¿;‚†ÓÎ=¦çW±?‰Ýž:”æ{´ëÐ@Õ0û¦'ž„e¸ó½†·oFÕùUw6MO#æÇyéR…f­’9fM,@³ßé¿"qoWg ¥wÖÝ_5óéôÔ¡4ßëµgÆìN:orÛu>סôLºû«îdBG#f7âŽ+UÔAé+gü¡!IÚP ‹ÇPOÛyѺmÛ]’ø!þ“
-ÎôSÞ¶‘´YoˆÖò¢`­ÆYG¦è4ª4°†„¯Ž…Çe‰^¯¬225ßïP\¾L•f¤¡i™QÐ;=õPÂçfôui¸éjLMO(ïR
-o:1¹m·/ô“)_Gï¡Y$uÒ]#!«Šž17”ž5êк³ozê¡ø×z—|5í»ñ
-%ë$–AQî®MWÂE’WæRÐ{h±ÈØ҇;.š²¤rTæ^ ÿžè°ùàÈa1ßyG"tø¨¦¨*³Þ'cšTÉJM>OáÑðraÆw彡ÀOÝïßó£Ä=”=5”æs4ëÐOèÚé@fùî×
-Íš15´ž¹„ŽFÎNòœÐd!¡cÈÒC iKƒ±[á¢RÊBWä]
-Ç䱬“_Å^¿ §§¥nTtiIÈYßí LS¦m¾×Pü¸û¨º¿jFÞíiîùÍh-ÆDžhLqp8Ny2£
-ÊŒ™*Šã 8q*¡’Õ2sFîòšÒ7’6$š /Ð,+Ⱦ©<óü*Ò›\À‚*W¤`Ç vQc»Êèª 8K6S¢U0â—Êæ“-Ò„‚ªöÂPʺJCOsÒ†D Éô•C*–‹Ê“º{džìÈŒZ9sž2Åú{(ô</ëèõ!‹K|J*…0%¸sH!ßL‚#èšéÒL™ z¦;’6$Z¤,ÇÍt±ÞŶ4Ý*pPùÚ|¾ÂŽ—ø8òºwºe³µÝ³„V! ixÓÉu~ºgcmH4g›ÍÙà†x
-“ælØæ¾k?BÚ\­µ yÈM*+Š…yê¡E~JËÜñfrwÙ•òø¤NÌÑV5b.ˆºmh…Âd’¸Ûq%|Þ_ §‘é³R8F—†;ÞV¢¿Û{¥8ߢ¿;††bëÖkCãµÉ»ÿÚkÓq—Ò|~Ê<V‰åïRÁ³(g¸g  ­wðµÊo$áÉó¶ó¢uÛ° !øõH”û‚ÏWóŸÏ˨¬‹6ðù^]ã¨L?YLÉ-•ÖˆãþXÙ(Š\³puTFËC>ZÊ•è ÚÏRϘ¦BYdB2Œ\Ð1à“
-æˆÃâ—Ý*«¶‘"÷°&MØ ‘j÷|Ïr? P"DjϤ° $&q`&08A „Å`ìc 9Ò“à‹‰ŽþA F þ20„FÊfn-³`,6b¨0‘kYÕH}‰‡$¡Ø©ÅTyþJkJŒIY|5ñl3‰òíe9¤Ô— ² vM¹ag(©|¬êȬ$>G«At
-Ò€¦,¬Í‘’ ˆ‘bÂvTß&‰Üûd¤J¥/ø‘P£t’Í$±'f§åöôóIÒ
-QJÚe—k ÷ÿïk"Oç
-YyKÂm9ŠXDÅv7;Ÿ›‰®
-Z!jEå@#M›bàÃÉå ¦¯êþ*”yˆë€‰®ê5!àp¥h<E›” ]ÆæZ±ÄQ5±²hkbOÍÇ#ÇŒ=
-8è¦6‡§‰ÐЄL"ÿ
-''¯ìǤªÁ) WIKôÃÂÃLB2
-ø©À1¬dν†ý ŠÅL”wÆ©®}Ÿkª/Æy@_è°€j‡"½6q'ºQ€ÔD¾Õ€ûc‚À
-g;/j–ÆÁ„àuͨâ¦aq©µD±#{’,v IâEùMá†Ã87ÌBRØ$ uÑx¦U«eŠ˜~V«àdsJ"á=yó›vMÑ$0#ì@ì"†‚ëõÔUjR—ÀWù\RTØ¡Lº~uT¸ÇëâE©¯eU{‘:EãÁÏR/ËVû„ýꤙtrÏ­ËÚÎåJîNòÈ\åu>åyUñ@3!ÝWðžì¯ñIÏ¢9{„í¦ÊÙTã3±Ãs&añ£°qʹ˱Žå¾a?Œñe*—¥ G:뤔‹hUìO®,îÜFOqÀÚ§*v¤T ,LPÈ6$½Ti
-l,UŠ+ñ|¸.·éUH3}%eÀG§Ið[©`#|T•¸¼_B)FÊ»
-›TMUrCSÁ:öðm’4Y2yŠÛ¥Ú Ö ™4JîhªzUJr ÖÞã;£ÂC¯<¬dѼł'•ƒ¾8tT«î†'ÊoPJÏRu"•/ذ
-üJéaxÈãÊcðêÀ\1Y‰çîÛb²/C@îp` Ð2Qù%@ª–‘T7‹¹ˆþ‚d ‚…Eä`[TS’R|Ï«WÁ“ü€åëq“ è!BH¦$¢àŸI¡$9¼}¨#ÌEI¡=…¡,¹ÒÑ+<é¸Ô»,ÉY™A‚¶Ââ~DSåŠÜ«x‘ÄTÊŒŠ€êœð”y| 4䃣€kIÉ#cÕ;¨x]•;Rа8ÇÊŠ55@•Ђ%Q–üÊKyy::R*‰—žðu[!öÜ//ð¢£Â“i‡òÀÔzñzl8šä‹¢>ž^%,V¨$Aƒç½– n`aït,T§Q9Ë‘ीÄ,Z(ðŠ)Ó³ôs,yƒdÑ?òÐN
-g*³ŒFéh\1Z•¦âöÁP/PW
-,5@EÁMOˆÖjæ3IBΡ•<*ü6©“êj Å2ì*M…r‡Çò ÔÌ“ï&ÁãL¨µp¹Üø¤Ã"¯¼rÁ­Ž
-uJpµ²¶ªU{€ð%äcº–(+»Ûä9Ä
-ÚDæéª°@(ôË> ¥ð|3LÙ¥zŒV*É#Ž Ÿ`paæ ¥½04F‡\åiçJ2YK *r羇)À¢¸˜ e*3½Õô°IÞLο–>¬0¯X›`‹pé©òÏ”ˆL-K<J7‡ VèJÖMQ¶ò
-4ÔêTŠ)xÚ|óc‹T”Ïak)€~VBÙ»ó~DÔÞø¸ KÇn*Qc,¬‹»úcq
-øEŸQ¡¢¢©â“Gà¸$óŠ–±‚ʾr{A,-ô²šž8khr%®Å“r),¼™Ô<p7, 7‚^0f¢W_r£ÿâP¦]5¨4•È㧪ð:8Ì^APMÚ
-M«UzZ‚Ý–U/œe³¡ä®¿ÇŒÎµ]6”6¢cÄr0÷i€f•;\g$N(/âQÔ;Ee¶‘#LhJ Ù²½¼{¡DkJðXJbFæV]a4ÉP‘Í/µêr·PÙ…¬C¢¢ðiØ {à iýdb1FEÌ eê¼Q¡ZJð^ÖáS Y·ÈhN”ß×€Ê$W>b } WN=YÝy«eíRqx,'(àœÝ¬@(ã> 2–I¥fD‹ÙÛ3€y±„3¡"æµd´TŒH1õ˜yTrÊWQ qHg\È»RÁ@¤h‹Øã>4ñ"œ …((ÇOžès)±˜£dúñ3h'v
-h¼:fž~ùâ,TžÊs/¤'Š36EU`õr7‹Ü õÕW¢8¤´³’b°.Ù"À Ý= ,m¸·§2(Pz8ë¿ôËî•›4yq…_ÕîŒÁÙFH¦§©‡RÕQg¾óº J¨ReÁ÷âaöœ’£9©ò™)k¤VÈËðMÕÃÅð’Š_¥Á¾çE$³Îaó#eäÑ"zQUˆLÆ֪¨*ykŠHŸ"MOù˜)C¡(…Î)™'rµÇFL™ýôXªwÌ€´´:¦ŠJ¯tü(¦2I!…MÛYº9A!à•3áÈ á’v#Ï´Ÿ”9V]dn Î&ù¹/ÿ¬Êb‚ÚdI?™‚ë‚ÓLfBb¾U˜W£ v$Oÿª= êFQ³äa(´@…WWW¶Œ¬òñËЦŸ¹©M£Õ S`táß,=;’
-ku8’ ȯ”ºçJ>&/!V˳N‡›5”O8ªüF¥Ê<¨Šzc¥3u©#ÜêÊktéÆëø”þ ¨T_)÷’R²gžŸ[­6Éõ^q¥ºÕÊ+S³ò—>ªc¥^…ë~‘S„­Ë†m(’Wi–„¯êd¢¥+è]ktÛÂKé«-ÍPÝšf£BÖÙÆjg~ȾT6A¶Kü®‡ýq“”@+jªù¤ªë_-=ªTUY¢(¬vî. J®Èî§[¦
-åîמ•!nIUhÑÌe¦S³~žùÑ¥¨CZ&¹G“†vºNCOÊÁ$
-Ï¡è‘;`RÀ
-©/™ò;  ¢]RÃqèá6Ë:æc†$gWæi4}&$²ÁìW4„Þ©-¨K££‰˜]‡B©¾f{•zÒÆWåÂÛøS¯mÞ˜;RõJ=:¥Éš¦…@| ŒK"ð8ñ!¯ž'9qñ2*ºAšFšTy4}ŠèPQ<‡ÆCòÑPx5äJVuÄ¼Þ .£\ÍHtˆyo‡û°–êÝ€¦¨Ý¡>¯qk0*B;¤¦*å …kh½-D.¡š\¼RÊ¥s—Ffµ'-<.Á*«pð
-qê¾LREs0véF˸ñ°Ì=7ƒ5xêúé6Ê:•9&ziDô"K¤Áñ€ Fû9¤Æ2Ûwì2Cóêp!²ªÿª|ó
-ÎQD|‚$« ?..¿¬l(YâyS¯¼ëDù®“àa÷ÎX]‘¤(ðMGôɱ"‹)мBwÀTP«=W¥ìßS”2öZA…;ÙEÃÖç3*COÈ#縠®A«¢L¹'j¨dàË‚g‘ "µc:Ó<¤eÐã‰S½sl DU–[™kœðÁðS{DQx£1þº5Y$üK±käêF
-Í<:\ˆ
-¿¾bqÄPX›áyÐf½!ÚÂcPY
-?èö&¾yc7· ›S{mHeù‘•U+&’»™.q%Eè GZ"XBíz!-ÊʳšIrž2þB”…‰ÎÄɧü·ô~¤dY3”ô^n(Ñ2eð¯ñ¡žx±ç1ͅȤ4Ù7€¢²¾æ²aŠIaÓ%S˜ªêŠý@þ,<Ê5-‘²Ð`&*±˜5ÜNÅp¡ Ö!o‹/v<HRAÅÞ?H+W”ŸÓ:Ü*X;¿ªn«‹JÂñXÌÃ2Ï1±ϤÚWgjÏk“2<ìu–ê€]Uâ'ßðÐÚ ­T  ´À¯Ê¹ªÒ/¢`W•›‹ñ¬²òÄDФæ;ÍQ•E¨æ”5)´…¬+…Iš{P jÅþFu¦,€râ&S•‹[•cOS¿oT= 7¶WI½h¸þd°ŠC¤<òÇêRýy úZ*Áî ø+'¦Ä È)õ#È*Þ”UÿŽiQBÄØa'¢ÉïʨÁC¨§"rfι-¨µT1Ôn¡s½‚r5B$äÖ"š)Òš5…R“ÜÏ)rw`Y—³G´ÔK¾(e”úñ8i(hlú˜{D3
-X©0Õ
-7•g”ô0•\ei[;X™…sS<î*ãÚ³›
-^e¡XÎ$·È ÿ
-—pœ](ÕÎdlL›ºBs×J8r­þA4`”$¯ï¸«”séÓðºÓ¹œ8‚<ósýP}™¬êWOþ^Ƭ`õ)}#HC}^HZHù¼[@¡
-£(%‘Ä×! :ëP§^R‰÷‰‹X­:QE¥P¶]çB aÈâUâú±_ne»Æ4¥o$mH•d¸&ÐgÚ_9‚ X†WDç"´~äB-¨(Áj –x²·a§á !&G!©4w:€ú §%àT QÈ?hÏU]¥%Ù
-bhCÀ{Õëæ^rWa•®2a *‹ÉÓ—yUQê“©2í‘߈ÌéD;On,[³‰rQ&bM*O,g«/¹LjñLSIAAOˆ'*­^&¾ÂNPFP Þá‘‹´ Ôõ¬k‰ûë†}¦€DÝ£¦^*Ž…ˆ²Ô§Q:/†¦dC#ûZPƒôˆÐb„ÆÑ|nÆvIÿ‰E™ìX¿ÞÑÍßóô·ÃJOÚ&¿ @aV¬;Ô´óïCÍ¿ƒ•Äî;Ô4Aè´8 ·ZÔ²Üä>DI7Žž»cÒ VŽC˜J
-ÇäôtÓ¡„y³M—«§£ÄÚ=_ ”}=Cêüªg*¡§¹'§|‚Eí¥£¡FD ÷Ò"…ó¢Ô7yhIܪ"] Ás¹:T¹óTÛ¸êí¥C ߢYM™º»å!«l÷k eF_gDÝõL$t4÷ÔÚ¦Ö(T 's»¦Š<+-¸@ÎiS"¨‡’ JßÓ,såtJßHÚhBp¦ya%¶ç±ïR*Çjõö¥”Ô(
-¼!ᾡÓ
-R Ï$Žõ ”ÝÖÓ®
-?Ïd$Iøª:¥!9+aQœ ´pøsQ4b/A9Å;­èin=eîr ;¸ë.%󰨞vÀ`%GŒXª¿ûBÏÇtŸ”¡wöMš<5Ÿ¶Õ¡ûM?væ}“&í4ýÀ™ï>búA³fÑwà‘Ó?8³ú¡‡ÒËÌÃí¿ôxÄÌ#íÙ›Ùäû;Š5i~>iÒV;nÝ÷}7)Œ endstream endobj 831 0 obj <</CreationDate(D:20080523233316-07'00')/Creator(Adobe Illustrator CS3)/ModDate(D:20080601013511-07'00')/Title(Basic RGB)>> endobj xref 0 839 0000000003 65535 f
-0000000016 00000 n
-0000042800 00000 n
-0000000004 00000 f
-0000000006 00000 f
-0000046686 00000 n
-0000000007 00000 f
-0000000008 00000 f
-0000000009 00000 f
-0000000010 00000 f
-0000000011 00000 f
-0000000012 00000 f
-0000000016 00000 f
-0000042851 00000 n
-0000046535 00000 n
-0000046566 00000 n
-0000000020 00000 f
-0000042922 00000 n
-0000046419 00000 n
-0000046450 00000 n
-0000000021 00000 f
-0000000022 00000 f
-0000000023 00000 f
-0000000024 00000 f
-0000000025 00000 f
-0000000026 00000 f
-0000000027 00000 f
-0000000028 00000 f
-0000000029 00000 f
-0000000030 00000 f
-0000000031 00000 f
-0000000032 00000 f
-0000000036 00000 f
-0000042993 00000 n
-0000046303 00000 n
-0000046334 00000 n
-0000000040 00000 f
-0000043064 00000 n
-0000046187 00000 n
-0000046218 00000 n
-0000000041 00000 f
-0000000042 00000 f
-0000000043 00000 f
-0000000044 00000 f
-0000000045 00000 f
-0000000046 00000 f
-0000000047 00000 f
-0000000048 00000 f
-0000000049 00000 f
-0000000050 00000 f
-0000000051 00000 f
-0000000052 00000 f
-0000000053 00000 f
-0000000054 00000 f
-0000000055 00000 f
-0000000056 00000 f
-0000000057 00000 f
-0000000058 00000 f
-0000000059 00000 f
-0000000060 00000 f
-0000000067 00000 f
-0000043135 00000 n
-0000046071 00000 n
-0000046102 00000 n
-0000043206 00000 n
-0000045955 00000 n
-0000045986 00000 n
-0000000068 00000 f
-0000000069 00000 f
-0000000070 00000 f
-0000000071 00000 f
-0000000072 00000 f
-0000000073 00000 f
-0000000074 00000 f
-0000000075 00000 f
-0000000076 00000 f
-0000000077 00000 f
-0000000078 00000 f
-0000000079 00000 f
-0000000080 00000 f
-0000000081 00000 f
-0000000082 00000 f
-0000000089 00000 f
-0000043277 00000 n
-0000045839 00000 n
-0000045870 00000 n
-0000043348 00000 n
-0000045723 00000 n
-0000045754 00000 n
-0000000090 00000 f
-0000000091 00000 f
-0000000092 00000 f
-0000000093 00000 f
-0000000094 00000 f
-0000000095 00000 f
-0000000096 00000 f
-0000000097 00000 f
-0000000098 00000 f
-0000000099 00000 f
-0000000100 00000 f
-0000000101 00000 f
-0000000102 00000 f
-0000000103 00000 f
-0000000104 00000 f
-0000000105 00000 f
-0000000106 00000 f
-0000000107 00000 f
-0000000108 00000 f
-0000000109 00000 f
-0000000110 00000 f
-0000000111 00000 f
-0000000118 00000 f
-0000043419 00000 n
-0000045605 00000 n
-0000045637 00000 n
-0000043493 00000 n
-0000045487 00000 n
-0000045519 00000 n
-0000000119 00000 f
-0000000120 00000 f
-0000000121 00000 f
-0000000122 00000 f
-0000000123 00000 f
-0000000124 00000 f
-0000000125 00000 f
-0000000126 00000 f
-0000000127 00000 f
-0000000128 00000 f
-0000000129 00000 f
-0000000130 00000 f
-0000000131 00000 f
-0000000132 00000 f
-0000000133 00000 f
-0000000134 00000 f
-0000000135 00000 f
-0000000136 00000 f
-0000000137 00000 f
-0000000138 00000 f
-0000000139 00000 f
-0000000140 00000 f
-0000000141 00000 f
-0000000142 00000 f
-0000000143 00000 f
-0000000144 00000 f
-0000000145 00000 f
-0000000146 00000 f
-0000000147 00000 f
-0000000148 00000 f
-0000000149 00000 f
-0000000150 00000 f
-0000000151 00000 f
-0000000152 00000 f
-0000000153 00000 f
-0000000154 00000 f
-0000000155 00000 f
-0000000156 00000 f
-0000000157 00000 f
-0000000158 00000 f
-0000000159 00000 f
-0000000160 00000 f
-0000000161 00000 f
-0000000162 00000 f
-0000000163 00000 f
-0000000164 00000 f
-0000000165 00000 f
-0000000166 00000 f
-0000000167 00000 f
-0000000168 00000 f
-0000000169 00000 f
-0000000170 00000 f
-0000000171 00000 f
-0000000172 00000 f
-0000000173 00000 f
-0000000174 00000 f
-0000000175 00000 f
-0000000176 00000 f
-0000000177 00000 f
-0000000178 00000 f
-0000000179 00000 f
-0000000180 00000 f
-0000000181 00000 f
-0000000182 00000 f
-0000000183 00000 f
-0000000184 00000 f
-0000000185 00000 f
-0000000186 00000 f
-0000000187 00000 f
-0000000188 00000 f
-0000000189 00000 f
-0000000190 00000 f
-0000000191 00000 f
-0000000192 00000 f
-0000000193 00000 f
-0000000194 00000 f
-0000000195 00000 f
-0000000196 00000 f
-0000000197 00000 f
-0000000198 00000 f
-0000000199 00000 f
-0000000200 00000 f
-0000000201 00000 f
-0000000202 00000 f
-0000000203 00000 f
-0000000204 00000 f
-0000000205 00000 f
-0000000206 00000 f
-0000000207 00000 f
-0000000208 00000 f
-0000000209 00000 f
-0000000210 00000 f
-0000000211 00000 f
-0000000212 00000 f
-0000000213 00000 f
-0000000214 00000 f
-0000000215 00000 f
-0000000216 00000 f
-0000000217 00000 f
-0000000224 00000 f
-0000043567 00000 n
-0000045369 00000 n
-0000045401 00000 n
-0000043641 00000 n
-0000045251 00000 n
-0000045283 00000 n
-0000000225 00000 f
-0000000226 00000 f
-0000000227 00000 f
-0000000228 00000 f
-0000000229 00000 f
-0000000230 00000 f
-0000000231 00000 f
-0000000232 00000 f
-0000000233 00000 f
-0000000234 00000 f
-0000000235 00000 f
-0000000236 00000 f
-0000000237 00000 f
-0000000238 00000 f
-0000000239 00000 f
-0000000240 00000 f
-0000000241 00000 f
-0000000242 00000 f
-0000000243 00000 f
-0000000244 00000 f
-0000000245 00000 f
-0000000246 00000 f
-0000000247 00000 f
-0000000248 00000 f
-0000000249 00000 f
-0000000250 00000 f
-0000000251 00000 f
-0000000252 00000 f
-0000000253 00000 f
-0000000254 00000 f
-0000000255 00000 f
-0000000256 00000 f
-0000000257 00000 f
-0000000258 00000 f
-0000000259 00000 f
-0000000260 00000 f
-0000000261 00000 f
-0000000262 00000 f
-0000000263 00000 f
-0000000264 00000 f
-0000000265 00000 f
-0000000266 00000 f
-0000000267 00000 f
-0000000268 00000 f
-0000000269 00000 f
-0000000270 00000 f
-0000000271 00000 f
-0000000272 00000 f
-0000000273 00000 f
-0000000274 00000 f
-0000000275 00000 f
-0000000276 00000 f
-0000000277 00000 f
-0000000278 00000 f
-0000000279 00000 f
-0000000280 00000 f
-0000000281 00000 f
-0000000282 00000 f
-0000000283 00000 f
-0000000284 00000 f
-0000000285 00000 f
-0000000286 00000 f
-0000000287 00000 f
-0000000288 00000 f
-0000000289 00000 f
-0000000290 00000 f
-0000000291 00000 f
-0000000292 00000 f
-0000000293 00000 f
-0000000294 00000 f
-0000000295 00000 f
-0000000296 00000 f
-0000000297 00000 f
-0000000298 00000 f
-0000000299 00000 f
-0000000300 00000 f
-0000000301 00000 f
-0000000302 00000 f
-0000000303 00000 f
-0000000304 00000 f
-0000000305 00000 f
-0000000306 00000 f
-0000000307 00000 f
-0000000308 00000 f
-0000000309 00000 f
-0000000310 00000 f
-0000000311 00000 f
-0000000312 00000 f
-0000000313 00000 f
-0000000314 00000 f
-0000000315 00000 f
-0000000316 00000 f
-0000000317 00000 f
-0000000318 00000 f
-0000000319 00000 f
-0000000320 00000 f
-0000000321 00000 f
-0000000322 00000 f
-0000000323 00000 f
-0000000324 00000 f
-0000000331 00000 f
-0000043715 00000 n
-0000045133 00000 n
-0000045165 00000 n
-0000043789 00000 n
-0000045015 00000 n
-0000045047 00000 n
-0000000332 00000 f
-0000000333 00000 f
-0000000334 00000 f
-0000000335 00000 f
-0000000336 00000 f
-0000000337 00000 f
-0000000338 00000 f
-0000000339 00000 f
-0000000340 00000 f
-0000000341 00000 f
-0000000342 00000 f
-0000000343 00000 f
-0000000344 00000 f
-0000000345 00000 f
-0000000346 00000 f
-0000000347 00000 f
-0000000348 00000 f
-0000000349 00000 f
-0000000350 00000 f
-0000000351 00000 f
-0000000352 00000 f
-0000000353 00000 f
-0000000354 00000 f
-0000000355 00000 f
-0000000356 00000 f
-0000000357 00000 f
-0000000358 00000 f
-0000000359 00000 f
-0000000360 00000 f
-0000000361 00000 f
-0000000362 00000 f
-0000000363 00000 f
-0000000364 00000 f
-0000000365 00000 f
-0000000366 00000 f
-0000000367 00000 f
-0000000368 00000 f
-0000000369 00000 f
-0000000370 00000 f
-0000000371 00000 f
-0000000372 00000 f
-0000000373 00000 f
-0000000374 00000 f
-0000000375 00000 f
-0000000376 00000 f
-0000000377 00000 f
-0000000378 00000 f
-0000000379 00000 f
-0000000380 00000 f
-0000000381 00000 f
-0000000382 00000 f
-0000000383 00000 f
-0000000384 00000 f
-0000000385 00000 f
-0000000386 00000 f
-0000000387 00000 f
-0000000388 00000 f
-0000000389 00000 f
-0000000390 00000 f
-0000000391 00000 f
-0000000392 00000 f
-0000000393 00000 f
-0000000394 00000 f
-0000000395 00000 f
-0000000396 00000 f
-0000000397 00000 f
-0000000398 00000 f
-0000000399 00000 f
-0000000400 00000 f
-0000000401 00000 f
-0000000402 00000 f
-0000000403 00000 f
-0000000404 00000 f
-0000000405 00000 f
-0000000406 00000 f
-0000000407 00000 f
-0000000408 00000 f
-0000000409 00000 f
-0000000410 00000 f
-0000000411 00000 f
-0000000412 00000 f
-0000000413 00000 f
-0000000414 00000 f
-0000000415 00000 f
-0000000416 00000 f
-0000000417 00000 f
-0000000418 00000 f
-0000000419 00000 f
-0000000420 00000 f
-0000000421 00000 f
-0000000422 00000 f
-0000000423 00000 f
-0000000424 00000 f
-0000000425 00000 f
-0000000426 00000 f
-0000000427 00000 f
-0000000428 00000 f
-0000000429 00000 f
-0000000430 00000 f
-0000000431 00000 f
-0000000432 00000 f
-0000000433 00000 f
-0000000434 00000 f
-0000000435 00000 f
-0000000436 00000 f
-0000000437 00000 f
-0000000438 00000 f
-0000000439 00000 f
-0000000440 00000 f
-0000000441 00000 f
-0000000442 00000 f
-0000000443 00000 f
-0000000444 00000 f
-0000000445 00000 f
-0000000446 00000 f
-0000000447 00000 f
-0000000448 00000 f
-0000000449 00000 f
-0000000450 00000 f
-0000000451 00000 f
-0000000452 00000 f
-0000000453 00000 f
-0000000454 00000 f
-0000000455 00000 f
-0000000456 00000 f
-0000000457 00000 f
-0000000458 00000 f
-0000000459 00000 f
-0000000460 00000 f
-0000000461 00000 f
-0000000468 00000 f
-0000043863 00000 n
-0000044897 00000 n
-0000044929 00000 n
-0000043937 00000 n
-0000044779 00000 n
-0000044811 00000 n
-0000000469 00000 f
-0000000470 00000 f
-0000000471 00000 f
-0000000472 00000 f
-0000000473 00000 f
-0000000474 00000 f
-0000000475 00000 f
-0000000476 00000 f
-0000000477 00000 f
-0000000478 00000 f
-0000000479 00000 f
-0000000480 00000 f
-0000000481 00000 f
-0000000482 00000 f
-0000000483 00000 f
-0000000484 00000 f
-0000000485 00000 f
-0000000486 00000 f
-0000000487 00000 f
-0000000488 00000 f
-0000000489 00000 f
-0000000490 00000 f
-0000000491 00000 f
-0000000492 00000 f
-0000000493 00000 f
-0000000494 00000 f
-0000000495 00000 f
-0000000496 00000 f
-0000000497 00000 f
-0000000498 00000 f
-0000000499 00000 f
-0000000500 00000 f
-0000000501 00000 f
-0000000502 00000 f
-0000000503 00000 f
-0000000504 00000 f
-0000000505 00000 f
-0000000506 00000 f
-0000000507 00000 f
-0000000508 00000 f
-0000000509 00000 f
-0000000510 00000 f
-0000000511 00000 f
-0000000512 00000 f
-0000000513 00000 f
-0000000514 00000 f
-0000000515 00000 f
-0000000516 00000 f
-0000000517 00000 f
-0000000518 00000 f
-0000000519 00000 f
-0000000520 00000 f
-0000000521 00000 f
-0000000522 00000 f
-0000000523 00000 f
-0000000524 00000 f
-0000000525 00000 f
-0000000526 00000 f
-0000000527 00000 f
-0000000528 00000 f
-0000000529 00000 f
-0000000530 00000 f
-0000000531 00000 f
-0000000532 00000 f
-0000000533 00000 f
-0000000534 00000 f
-0000000535 00000 f
-0000000536 00000 f
-0000000537 00000 f
-0000000538 00000 f
-0000000539 00000 f
-0000000540 00000 f
-0000000541 00000 f
-0000000542 00000 f
-0000000543 00000 f
-0000000544 00000 f
-0000000545 00000 f
-0000000546 00000 f
-0000000547 00000 f
-0000000548 00000 f
-0000000549 00000 f
-0000000550 00000 f
-0000000551 00000 f
-0000000552 00000 f
-0000000553 00000 f
-0000000554 00000 f
-0000000555 00000 f
-0000000556 00000 f
-0000000557 00000 f
-0000000558 00000 f
-0000000559 00000 f
-0000000560 00000 f
-0000000561 00000 f
-0000000562 00000 f
-0000000563 00000 f
-0000000564 00000 f
-0000000565 00000 f
-0000000566 00000 f
-0000000567 00000 f
-0000000568 00000 f
-0000000569 00000 f
-0000000570 00000 f
-0000000571 00000 f
-0000000572 00000 f
-0000000573 00000 f
-0000000574 00000 f
-0000000575 00000 f
-0000000576 00000 f
-0000000577 00000 f
-0000000578 00000 f
-0000000579 00000 f
-0000000580 00000 f
-0000000581 00000 f
-0000000582 00000 f
-0000000583 00000 f
-0000000584 00000 f
-0000000585 00000 f
-0000000586 00000 f
-0000000587 00000 f
-0000000588 00000 f
-0000000589 00000 f
-0000000590 00000 f
-0000000591 00000 f
-0000000592 00000 f
-0000000593 00000 f
-0000000594 00000 f
-0000000595 00000 f
-0000000596 00000 f
-0000000597 00000 f
-0000000598 00000 f
-0000000599 00000 f
-0000000600 00000 f
-0000000601 00000 f
-0000000602 00000 f
-0000000603 00000 f
-0000000604 00000 f
-0000000605 00000 f
-0000000606 00000 f
-0000000607 00000 f
-0000000608 00000 f
-0000000615 00001 f
-0000044011 00000 n
-0000044661 00000 n
-0000044693 00000 n
-0000044085 00000 n
-0000044543 00000 n
-0000044575 00000 n
-0000000616 00000 f
-0000000617 00000 f
-0000000618 00000 f
-0000000619 00000 f
-0000000620 00000 f
-0000000621 00000 f
-0000000622 00000 f
-0000000623 00000 f
-0000000624 00000 f
-0000000625 00000 f
-0000000626 00000 f
-0000000627 00000 f
-0000000628 00000 f
-0000000629 00000 f
-0000000630 00000 f
-0000000631 00000 f
-0000000632 00000 f
-0000000633 00000 f
-0000000634 00000 f
-0000000635 00000 f
-0000000636 00000 f
-0000000637 00000 f
-0000000638 00000 f
-0000000639 00000 f
-0000000640 00000 f
-0000000641 00000 f
-0000000642 00000 f
-0000000643 00000 f
-0000000644 00000 f
-0000000645 00000 f
-0000000646 00000 f
-0000000647 00000 f
-0000000648 00000 f
-0000000649 00000 f
-0000000650 00000 f
-0000000651 00000 f
-0000000652 00000 f
-0000000653 00000 f
-0000000654 00000 f
-0000000655 00000 f
-0000000656 00000 f
-0000000657 00000 f
-0000000658 00000 f
-0000000659 00000 f
-0000000660 00000 f
-0000000661 00000 f
-0000000662 00000 f
-0000000663 00000 f
-0000000664 00000 f
-0000000665 00000 f
-0000000666 00000 f
-0000000667 00000 f
-0000000668 00000 f
-0000000669 00000 f
-0000000670 00000 f
-0000000671 00000 f
-0000000672 00000 f
-0000000673 00000 f
-0000000674 00000 f
-0000000675 00000 f
-0000000676 00000 f
-0000000677 00000 f
-0000000678 00000 f
-0000000679 00000 f
-0000000680 00000 f
-0000000681 00000 f
-0000000682 00000 f
-0000000683 00000 f
-0000000684 00000 f
-0000000685 00000 f
-0000000686 00000 f
-0000000687 00000 f
-0000000688 00000 f
-0000000689 00000 f
-0000000690 00000 f
-0000000691 00000 f
-0000000692 00000 f
-0000000693 00000 f
-0000000694 00000 f
-0000000695 00000 f
-0000000696 00000 f
-0000000697 00000 f
-0000000698 00000 f
-0000000699 00000 f
-0000000700 00000 f
-0000000701 00000 f
-0000000702 00000 f
-0000000703 00000 f
-0000000704 00000 f
-0000000705 00000 f
-0000000706 00000 f
-0000000707 00000 f
-0000000708 00000 f
-0000000709 00000 f
-0000000710 00000 f
-0000000711 00000 f
-0000000712 00001 f
-0000000713 00000 f
-0000000714 00000 f
-0000000715 00000 f
-0000000716 00000 f
-0000000717 00000 f
-0000000718 00000 f
-0000000727 00000 f
-0000167168 00000 n
-0000167244 00000 n
-0000167491 00000 n
-0000168436 00000 n
-0000177026 00000 n
-0000242615 00000 n
-0000308204 00000 n
-0000373793 00000 n
-0000000735 00001 f
-0000046651 00000 n
-0000044159 00000 n
-0000044425 00000 n
-0000044457 00000 n
-0000044233 00000 n
-0000044307 00000 n
-0000044339 00000 n
-0000000738 00001 f
-0000087724 00000 n
-0000088104 00000 n
-0000000743 00001 f
-0000087578 00000 n
-0000087752 00000 n
-0000087873 00000 n
-0000087983 00000 n
-0000000744 00001 f
-0000000745 00001 f
-0000000746 00001 f
-0000000748 00001 f
-0000150024 00000 n
-0000000749 00001 f
-0000000750 00001 f
-0000000751 00001 f
-0000000753 00001 f
-0000150667 00000 n
-0000000760 00001 f
-0000150780 00000 n
-0000150592 00000 n
-0000165350 00000 n
-0000150270 00000 n
-0000150204 00000 n
-0000150561 00000 n
-0000000766 00001 f
-0000150088 00000 n
-0000165378 00000 n
-0000165426 00000 n
-0000165481 00000 n
-0000138699 00000 n
-0000000767 00001 f
-0000000769 00001 f
-0000149960 00000 n
-0000000772 00001 f
-0000055709 00000 n
-0000139024 00000 n
-0000000773 00001 f
-0000000775 00001 f
-0000149896 00000 n
-0000000776 00001 f
-0000000778 00001 f
-0000143111 00000 n
-0000000779 00001 f
-0000000781 00001 f
-0000149832 00000 n
-0000000782 00001 f
-0000000784 00001 f
-0000143604 00000 n
-0000000785 00001 f
-0000000787 00001 f
-0000149768 00000 n
-0000000788 00001 f
-0000000790 00001 f
-0000144100 00000 n
-0000000791 00001 f
-0000000793 00001 f
-0000149704 00000 n
-0000000794 00001 f
-0000000796 00001 f
-0000144596 00000 n
-0000000797 00001 f
-0000000799 00001 f
-0000149640 00000 n
-0000000800 00001 f
-0000000802 00001 f
-0000145086 00000 n
-0000000803 00001 f
-0000000805 00001 f
-0000149576 00000 n
-0000000806 00001 f
-0000000808 00001 f
-0000145580 00000 n
-0000000809 00001 f
-0000000811 00001 f
-0000149512 00000 n
-0000000812 00001 f
-0000000000 00001 f
-0000146075 00000 n
-0000056912 00000 n
-0000074869 00000 n
-0000057259 00000 n
-0000064906 00000 n
-0000057462 00000 n
-0000057801 00000 n
-0000055823 00000 n
-0000055938 00000 n
-0000056054 00000 n
-0000056178 00000 n
-0000056302 00000 n
-0000056416 00000 n
-0000056540 00000 n
-0000056664 00000 n
-0000056788 00000 n
-0000047377 00000 n
-0000054212 00000 n
-0000390137 00000 n
-0000075136 00000 n
-0000065179 00000 n
-0000058058 00000 n
-0000166604 00000 n
-0000166654 00000 n
-0000054278 00000 n
-0000000440 00000 n
-trailer <</Size 839/Root 1 0 R/Info 831 0 R/ID[<AA4894F46BEB4C23B205C9EE66357C21><99338DF970B2468FBD32ED101BCCED08>]>> startxref 390278 %%EOF \ No newline at end of file
diff --git a/res/drawable/appointment_indicator_leftside_1.9.png b/res/drawable/appointment_indicator_leftside_1.9.png
deleted file mode 100644
index 5e402359f..000000000
--- a/res/drawable/appointment_indicator_leftside_1.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_10.9.png b/res/drawable/appointment_indicator_leftside_10.9.png
deleted file mode 100644
index d0cb144a9..000000000
--- a/res/drawable/appointment_indicator_leftside_10.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_11.9.png b/res/drawable/appointment_indicator_leftside_11.9.png
deleted file mode 100644
index 034f496e2..000000000
--- a/res/drawable/appointment_indicator_leftside_11.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_12.9.png b/res/drawable/appointment_indicator_leftside_12.9.png
deleted file mode 100644
index 6371b3a21..000000000
--- a/res/drawable/appointment_indicator_leftside_12.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_13.9.png b/res/drawable/appointment_indicator_leftside_13.9.png
deleted file mode 100644
index a8b42c6db..000000000
--- a/res/drawable/appointment_indicator_leftside_13.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_14.9.png b/res/drawable/appointment_indicator_leftside_14.9.png
deleted file mode 100644
index a69e519cf..000000000
--- a/res/drawable/appointment_indicator_leftside_14.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_15.9.png b/res/drawable/appointment_indicator_leftside_15.9.png
deleted file mode 100644
index 5d684704e..000000000
--- a/res/drawable/appointment_indicator_leftside_15.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_16.9.png b/res/drawable/appointment_indicator_leftside_16.9.png
deleted file mode 100644
index d9420c1b1..000000000
--- a/res/drawable/appointment_indicator_leftside_16.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_17.9.png b/res/drawable/appointment_indicator_leftside_17.9.png
deleted file mode 100644
index d0875c49c..000000000
--- a/res/drawable/appointment_indicator_leftside_17.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_18.9.png b/res/drawable/appointment_indicator_leftside_18.9.png
deleted file mode 100644
index fc152f733..000000000
--- a/res/drawable/appointment_indicator_leftside_18.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_19.9.png b/res/drawable/appointment_indicator_leftside_19.9.png
deleted file mode 100644
index 6506a94d0..000000000
--- a/res/drawable/appointment_indicator_leftside_19.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_2.9.png b/res/drawable/appointment_indicator_leftside_2.9.png
deleted file mode 100644
index 3baf5cc10..000000000
--- a/res/drawable/appointment_indicator_leftside_2.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_20.9.png b/res/drawable/appointment_indicator_leftside_20.9.png
deleted file mode 100644
index 28340bada..000000000
--- a/res/drawable/appointment_indicator_leftside_20.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_21.9.png b/res/drawable/appointment_indicator_leftside_21.9.png
deleted file mode 100644
index 5319f079e..000000000
--- a/res/drawable/appointment_indicator_leftside_21.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_3.9.png b/res/drawable/appointment_indicator_leftside_3.9.png
deleted file mode 100644
index 98507913a..000000000
--- a/res/drawable/appointment_indicator_leftside_3.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_4.9.png b/res/drawable/appointment_indicator_leftside_4.9.png
deleted file mode 100644
index e344ccb77..000000000
--- a/res/drawable/appointment_indicator_leftside_4.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_5.9.png b/res/drawable/appointment_indicator_leftside_5.9.png
deleted file mode 100644
index 11b4dfbf0..000000000
--- a/res/drawable/appointment_indicator_leftside_5.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_6.9.png b/res/drawable/appointment_indicator_leftside_6.9.png
deleted file mode 100644
index 7419d473e..000000000
--- a/res/drawable/appointment_indicator_leftside_6.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_7.9.png b/res/drawable/appointment_indicator_leftside_7.9.png
deleted file mode 100644
index 0a3a27226..000000000
--- a/res/drawable/appointment_indicator_leftside_7.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_8.9.png b/res/drawable/appointment_indicator_leftside_8.9.png
deleted file mode 100644
index db18d276e..000000000
--- a/res/drawable/appointment_indicator_leftside_8.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/appointment_indicator_leftside_9.9.png b/res/drawable/appointment_indicator_leftside_9.9.png
deleted file mode 100644
index 5037de83c..000000000
--- a/res/drawable/appointment_indicator_leftside_9.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/attached_image_placeholder.png b/res/drawable/attached_image_placeholder.png
deleted file mode 100644
index 90acbf772..000000000
--- a/res/drawable/attached_image_placeholder.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/button_indicator_next.png b/res/drawable/button_indicator_next.png
deleted file mode 100644
index 784d72225..000000000
--- a/res/drawable/button_indicator_next.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/divider_horizontal_email.9.png b/res/drawable/divider_horizontal_email.9.png
deleted file mode 100644
index 1f56364f2..000000000
--- a/res/drawable/divider_horizontal_email.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/email_quoted_bar.9.png b/res/drawable/email_quoted_bar.9.png
deleted file mode 100644
index 3d197d5c8..000000000
--- a/res/drawable/email_quoted_bar.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/expander_ic_folder.xml b/res/drawable/expander_ic_folder.xml
deleted file mode 100644
index d82c00ab9..000000000
--- a/res/drawable/expander_ic_folder.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_expanded="true"
- android:drawable="@drawable/expander_ic_folder_maximized" />
- <item android:drawable="@drawable/expander_ic_folder_minimized" />
-</selector>
diff --git a/res/drawable/expander_ic_folder_maximized.9.png b/res/drawable/expander_ic_folder_maximized.9.png
deleted file mode 100644
index c7ff2ac55..000000000
--- a/res/drawable/expander_ic_folder_maximized.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/expander_ic_folder_minimized.9.png b/res/drawable/expander_ic_folder_minimized.9.png
deleted file mode 100644
index 5b5fdb0aa..000000000
--- a/res/drawable/expander_ic_folder_minimized.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/folder_message_list_child_background.xml b/res/drawable/folder_message_list_child_background.xml
deleted file mode 100644
index a39fb292e..000000000
--- a/res/drawable/folder_message_list_child_background.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_window_focused="false" android:state_selected="true"
- android:drawable="@color/folder_message_list_child_background" />
- <item android:state_selected="true"
- android:drawable="@android:color/transparent" />
- <item android:state_pressed="true" android:state_selected="false"
- android:drawable="@android:color/transparent" />
- <item android:state_selected="false"
- android:drawable="@color/folder_message_list_child_background" />
-</selector>
diff --git a/res/drawable/ic_email_attachment.png b/res/drawable/ic_email_attachment.png
deleted file mode 100644
index 6fe0d3ebe..000000000
--- a/res/drawable/ic_email_attachment.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/ic_email_attachment_small.png b/res/drawable/ic_email_attachment_small.png
deleted file mode 100644
index eaed42c9a..000000000
--- a/res/drawable/ic_email_attachment_small.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/ic_email_thread_open_top_default.9.png b/res/drawable/ic_email_thread_open_top_default.9.png
deleted file mode 100644
index 9aebde9d7..000000000
--- a/res/drawable/ic_email_thread_open_top_default.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/ic_menu_forward_mail.png b/res/drawable/ic_menu_forward_mail.png
deleted file mode 100644
index 97b63afeb..000000000
--- a/res/drawable/ic_menu_forward_mail.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/ic_menu_reply.png b/res/drawable/ic_menu_reply.png
deleted file mode 100644
index bd18b582b..000000000
--- a/res/drawable/ic_menu_reply.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/ic_menu_reply_all.png b/res/drawable/ic_menu_reply_all.png
deleted file mode 100644
index 731e9971b..000000000
--- a/res/drawable/ic_menu_reply_all.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/ic_menu_save_draft.png b/res/drawable/ic_menu_save_draft.png
deleted file mode 100644
index 723193323..000000000
--- a/res/drawable/ic_menu_save_draft.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/ic_mms_attachment_small.png b/res/drawable/ic_mms_attachment_small.png
deleted file mode 100644
index a661ce49d..000000000
--- a/res/drawable/ic_mms_attachment_small.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/icon.png b/res/drawable/icon.png
deleted file mode 100644
index 590ed705d..000000000
--- a/res/drawable/icon.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/stat_notify_email_generic.png b/res/drawable/stat_notify_email_generic.png
deleted file mode 100644
index 686033f8d..000000000
--- a/res/drawable/stat_notify_email_generic.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/text_box.9.png b/res/drawable/text_box.9.png
deleted file mode 100644
index e7d4207b8..000000000
--- a/res/drawable/text_box.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/text_box_light.9.png b/res/drawable/text_box_light.9.png
deleted file mode 100755
index 888bbf2e3..000000000
--- a/res/drawable/text_box_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/layout-land/message_view.xml b/res/layout-land/message_view.xml
deleted file mode 100644
index 45a9eda43..000000000
--- a/res/layout-land/message_view.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="@android:color/white">
- <ScrollView
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:scrollbarStyle="outsideInset"
- android:fadingEdge="none">
- <LinearLayout
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1">
-
- <include layout="@layout/message_view_header" />
-
- </LinearLayout>
- </ScrollView>
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingTop="5dip"
- android:paddingLeft="4dip"
- android:paddingRight="4dip"
- android:paddingBottom="1dip"
- android:background="@android:drawable/bottom_bar">
- <Button
- android:id="@+id/reply"
- android:text="@string/reply_action"
- android:layout_height="fill_parent"
- android:layout_width="0dip"
- android:layout_weight="1" />
- <Button
- android:id="@+id/reply_all"
- android:text="@string/reply_all_action"
- android:layout_height="fill_parent"
- android:layout_width="0dip"
- android:layout_weight="1" />
- <Button
- android:id="@+id/delete"
- android:text="@string/delete_action"
- android:layout_height="fill_parent"
- android:layout_width="0dip"
- android:layout_weight="1" />
- </LinearLayout>
-</LinearLayout>
diff --git a/res/layout/account_setup_account_type.xml b/res/layout/account_setup_account_type.xml
deleted file mode 100644
index fbbcf7461..000000000
--- a/res/layout/account_setup_account_type.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- >
- <TextView
- android:text="@string/account_setup_account_type_instructions"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorPrimary"
- />
- <Button
- android:id="@+id/pop"
- android:text="@string/account_setup_account_type_pop_action"
- android:layout_height="wrap_content"
- android:layout_width="150sp"
- android:minWidth="@dimen/button_minWidth"
- android:layout_gravity="center_horizontal"
- />
- <Button
- android:id="@+id/imap"
- android:text="@string/account_setup_account_type_imap_action"
- android:layout_height="wrap_content"
- android:layout_width="150sp"
- android:minWidth="@dimen/button_minWidth"
- android:layout_gravity="center_horizontal"
- />
-</LinearLayout>
diff --git a/res/layout/account_setup_basics.xml b/res/layout/account_setup_basics.xml
deleted file mode 100644
index 31efc8551..000000000
--- a/res/layout/account_setup_basics.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- >
- <TextView
- android:text="@string/account_setup_basics_instructions"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorPrimary"
- />
- <EditText
- android:id="@+id/account_email"
- android:hint="@string/account_setup_basics_email_hint"
- android:inputType="textEmailAddress"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- />
- <EditText
- android:id="@+id/account_password"
- android:hint="@string/account_setup_basics_password_hint"
- android:inputType="textPassword"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:nextFocusDown="@+id/next"
- />
- <CheckBox
- android:id="@+id/account_default"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:text="@string/account_setup_basics_default_label"
- android:visibility="gone"
- />
- <View
- android:layout_width="fill_parent"
- android:layout_height="0px"
- android:layout_weight="1"
- />
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="54dip"
- android:background="@android:drawable/bottom_bar"
- >
- <Button
- android:id="@+id/manual_setup"
- android:text="@string/account_setup_basics_manual_setup_action"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:minWidth="@dimen/button_minWidth"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- />
- <Button
- android:id="@+id/next"
- android:text="@string/next_action"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:minWidth="@dimen/button_minWidth"
- android:drawableRight="@drawable/button_indicator_next"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- />
- </RelativeLayout>
-</LinearLayout>
diff --git a/res/layout/account_setup_check_settings.xml b/res/layout/account_setup_check_settings.xml
deleted file mode 100644
index 3d5017037..000000000
--- a/res/layout/account_setup_check_settings.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical">
- <View
- android:layout_width="fill_parent"
- android:layout_height="100sp" />
- <TextView
- android:id="@+id/message"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:gravity="center_horizontal"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorPrimary"
- android:paddingBottom="6px" />
- <ProgressBar
- android:id="@+id/progress"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- style="?android:attr/progressBarStyleHorizontal" />
- <View
- android:layout_width="fill_parent"
- android:layout_height="0px"
- android:layout_weight="1" />
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="54dip"
- android:background="@android:drawable/bottom_bar">
- <Button
- android:id="@+id/cancel"
- android:text="@string/cancel_action"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:minWidth="@dimen/button_minWidth"
- android:layout_centerVertical="true" />
- </RelativeLayout>
-</LinearLayout>
diff --git a/res/layout/account_setup_incoming.xml b/res/layout/account_setup_incoming.xml
deleted file mode 100644
index 2414a5dee..000000000
--- a/res/layout/account_setup_incoming.xml
+++ /dev/null
@@ -1,131 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<ScrollView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:scrollbarStyle="outsideInset">
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical">
- <TextView
- android:text="@string/account_setup_incoming_username_label"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary" />
- <EditText
- android:id="@+id/account_username"
- android:inputType="textEmailAddress"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent" />
- <TextView
- android:text="@string/account_setup_incoming_password_label"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary" />
- <EditText
- android:id="@+id/account_password"
- android:inputType="textPassword"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent" />
- <!-- This text may be changed in code if the server is IMAP, etc. -->
- <TextView
- android:id="@+id/account_server_label"
- android:text="@string/account_setup_incoming_pop_server_label"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary" />
- <!-- Note: we use inputType=textUri as the closest approximation to a server name -->
- <EditText
- android:id="@+id/account_server"
- android:inputType="textUri"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent" />
- <TextView
- android:text="@string/account_setup_incoming_port_label"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary" />
- <EditText
- android:id="@+id/account_port"
- android:inputType="number"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent" />
- <TextView
- android:text="@string/account_setup_incoming_security_label"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary" />
- <Spinner
- android:id="@+id/account_security_type"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent" />
- <TextView
- android:id="@+id/account_delete_policy_label"
- android:text="@string/account_setup_incoming_delete_policy_label"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary" />
- <Spinner
- android:id="@+id/account_delete_policy"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent" />
- <LinearLayout
- android:id="@+id/imap_path_prefix_section"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
- <TextView
- android:text="@string/account_setup_incoming_imap_path_prefix_label"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary" />
- <EditText
- android:id="@+id/imap_path_prefix"
- android:hint="@string/account_setup_incoming_imap_path_prefix_hint"
- inputType="text"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent" />
- </LinearLayout>
- <View
- android:layout_width="fill_parent"
- android:layout_height="0px"
- android:layout_weight="1" />
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="54dip"
- android:background="@android:drawable/bottom_bar">
- <Button
- android:id="@+id/next"
- android:text="@string/next_action"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:minWidth="@dimen/button_minWidth"
- android:drawableRight="@drawable/button_indicator_next"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true" />
- </RelativeLayout>
- </LinearLayout>
-</ScrollView>
diff --git a/res/layout/account_setup_names.xml b/res/layout/account_setup_names.xml
deleted file mode 100644
index 0930ca53c..000000000
--- a/res/layout/account_setup_names.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical">
- <TextView
- android:text="@string/account_setup_names_instructions"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorPrimary" />
- <TextView
- android:text="@string/account_setup_names_account_name_label"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary" />
- <EditText
- android:id="@+id/account_description"
- android:inputType="textCapWords"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent" />
- <TextView
- android:text="@string/account_setup_names_user_name_label"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary" />
- <EditText
- android:id="@+id/account_name"
- android:inputType="textPersonName"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent" />
- <View
- android:layout_height="0px"
- android:layout_width="fill_parent"
- android:layout_weight="1" />
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="54dip"
- android:background="@android:drawable/bottom_bar">
- <Button
- android:id="@+id/done"
- android:text="@string/done_action"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:minWidth="@dimen/button_minWidth"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true" />
- </RelativeLayout>
-</LinearLayout>
diff --git a/res/layout/account_setup_options.xml b/res/layout/account_setup_options.xml
deleted file mode 100644
index a0a4e7316..000000000
--- a/res/layout/account_setup_options.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical">
- <TextView
- android:text="@string/account_setup_options_mail_check_frequency_label"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary" />
- <Spinner
- android:id="@+id/account_check_frequency"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent" />
- <CheckBox
- android:id="@+id/account_default"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:text="@string/account_setup_options_default_label" />
- <CheckBox
- android:id="@+id/account_notify"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:text="@string/account_setup_options_notify_label" />
- <View
- android:layout_width="fill_parent"
- android:layout_height="0px"
- android:layout_weight="1" />
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="54dip"
- android:background="@android:drawable/bottom_bar">
- <Button
- android:id="@+id/next"
- android:text="@string/next_action"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:minWidth="@dimen/button_minWidth"
- android:drawableRight="@drawable/button_indicator_next"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true" />
- </RelativeLayout>
-</LinearLayout>
diff --git a/res/layout/account_setup_outgoing.xml b/res/layout/account_setup_outgoing.xml
deleted file mode 100644
index 02de415bf..000000000
--- a/res/layout/account_setup_outgoing.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<ScrollView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:scrollbarStyle="outsideInset">
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical">
- <TextView
- android:text="@string/account_setup_outgoing_smtp_server_label"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary" />
- <!-- Note: we use inputType=textUri as the closest approximation to a server name -->
- <EditText
- android:id="@+id/account_server"
- android:inputType="textUri"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent" />
- <TextView
- android:text="@string/account_setup_outgoing_port_label"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary" />
- <EditText
- android:id="@+id/account_port"
- android:inputType="number"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent" />
- <TextView
- android:text="@string/account_setup_outgoing_security_label"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary" />
- <Spinner
- android:id="@+id/account_security_type"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent" />
- <CheckBox
- android:id="@+id/account_require_login"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="@string/account_setup_outgoing_require_login_label" />
- <LinearLayout
- android:id="@+id/account_require_login_settings"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- android:visibility="gone">
- <TextView
- android:text="@string/account_setup_outgoing_username_label"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary" />
- <EditText
- android:id="@+id/account_username"
- android:inputType="textEmailAddress"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent" />
- <TextView
- android:text="@string/account_setup_outgoing_password_label"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary" />
- <EditText
- android:id="@+id/account_password"
- android:inputType="textPassword"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent" />
- </LinearLayout>
- <View
- android:layout_width="fill_parent"
- android:layout_height="0px"
- android:layout_weight="1" />
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="54dip"
- android:background="@android:drawable/bottom_bar">
- <Button
- android:id="@+id/next"
- android:text="@string/next_action"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:minWidth="@dimen/button_minWidth"
- android:drawableRight="@drawable/button_indicator_next"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true" />
- </RelativeLayout>
- </LinearLayout>
-</ScrollView>
diff --git a/res/layout/accounts.xml b/res/layout/accounts.xml
deleted file mode 100644
index f1f0792f3..000000000
--- a/res/layout/accounts.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <ListView
- android:id="@android:id/list"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- />
- <LinearLayout
- android:id="@+id/empty"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical">
- <TextView
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textSize="20sp"
- android:text="@string/accounts_welcome"
- android:textColor="?android:attr/textColorPrimary" />
- <View
- android:layout_width="fill_parent"
- android:layout_height="0px"
- android:layout_weight="1" />
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="54dip"
- android:background="@android:drawable/bottom_bar">
- <Button
- android:id="@+id/add_new_account"
- android:layout_width="wrap_content"
- android:minWidth="@dimen/button_minWidth"
- android:layout_height="wrap_content"
- android:text="@string/next_action"
- android:drawableRight="@drawable/button_indicator_next"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true" />
- </RelativeLayout>
- </LinearLayout>
-</FrameLayout>
diff --git a/res/layout/accounts_item.xml b/res/layout/accounts_item.xml
deleted file mode 100644
index 3774182c9..000000000
--- a/res/layout/accounts_item.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:orientation="horizontal"
- android:gravity="center_vertical"
- android:paddingRight="4px">
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingLeft="6px">
- <TextView
- android:id="@+id/description"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorPrimary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <TextView
- android:id="@+id/email"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- </LinearLayout>
- <View
- android:layout_height="fill_parent"
- android:layout_width="0px"
- android:layout_weight="1" />
- <TextView
- android:id="@+id/new_message_count"
- android:ellipsize="end"
- android:singleLine="true"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:textColor="?android:attr/textColorPrimary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@drawable/text_box_light"
- android:paddingLeft="10px"
- android:paddingRight="10px"
- android:minWidth="64px"
- android:gravity="right" />
-</LinearLayout>
diff --git a/res/layout/debug.xml b/res/layout/debug.xml
deleted file mode 100644
index 1cfd17745..000000000
--- a/res/layout/debug.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- >
- <TextView
- android:id="@+id/version"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="@string/debug_version_fmt"
- />
- <CheckBox
- android:id="@+id/debug_logging"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/debug_enable_debug_logging_label"
- />
- <CheckBox
- android:id="@+id/sensitive_logging"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/debug_enable_sensitive_logging_label"
- />
-</LinearLayout>
diff --git a/res/layout/folder_message_list_child.xml b/res/layout/folder_message_list_child.xml
deleted file mode 100644
index 0867c5169..000000000
--- a/res/layout/folder_message_list_child.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:paddingRight="10px"
- android:background="@drawable/folder_message_list_child_background">
- <View
- android:id="@+id/chip"
- android:background="@drawable/appointment_indicator_leftside_1"
- android:layout_width="4px"
- android:layout_height="56px"
- android:layout_centerVertical="true" />
- <TextView
- android:id="@+id/from"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/chip"
- android:ellipsize="end"
- android:singleLine="true"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorPrimary"
- android:paddingLeft="30px"
- android:drawablePadding="4px"
- android:paddingTop="12px" />
- <TextView
- android:id="@+id/date"
- android:ellipsize="end"
- android:singleLine="true"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_alignBaseline="@+id/subject" />
- <TextView
- android:id="@+id/subject"
- android:ellipsize="end"
- android:singleLine="true"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondary"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_below="@id/from"
- android:layout_alignLeft="@id/from"
- android:layout_toLeftOf="@id/date"
- android:paddingLeft="30px"
- android:layout_marginRight="6dip" />
-</RelativeLayout>
diff --git a/res/layout/folder_message_list_child_footer.xml b/res/layout/folder_message_list_child_footer.xml
deleted file mode 100644
index 434be779e..000000000
--- a/res/layout/folder_message_list_child_footer.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:gravity="center"
- android:orientation="horizontal">
- <ProgressBar
- android:id="@+id/progress"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- style="?android:attr/progressBarStyleSmall"
- android:paddingRight="10px"
- />
- <TextView
- android:id="@+id/main_text"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorPrimary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center"
- />
-</LinearLayout>
diff --git a/res/layout/folder_message_list_group.xml b/res/layout/folder_message_list_group.xml
deleted file mode 100644
index dc8d75dca..000000000
--- a/res/layout/folder_message_list_group.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:orientation="horizontal"
- android:gravity="center_vertical"
- android:paddingLeft="36px"
- android:paddingRight="4px">
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:gravity="center_vertical">
- <TextView
- android:id="@+id/folder_name"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:textColor="?android:attr/textColorPrimary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <TextView
- android:id="@+id/folder_status"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorTertiary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- </LinearLayout>
- <View
- android:layout_height="0dip"
- android:layout_width="0dip"
- android:layout_weight="1" />
- <TextView
- android:id="@+id/new_message_count"
- android:ellipsize="end"
- android:singleLine="true"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:textColor="?android:attr/textColorPrimary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@drawable/text_box_light"
- android:paddingLeft="10px"
- android:paddingRight="10px"
- android:minWidth="64px"
- android:gravity="right" />
-</LinearLayout>
diff --git a/res/layout/message_compose.xml b/res/layout/message_compose.xml
deleted file mode 100644
index 3cda691c3..000000000
--- a/res/layout/message_compose.xml
+++ /dev/null
@@ -1,140 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="fill_parent" android:layout_width="fill_parent"
- android:orientation="vertical" android:background="#ffffff">
- <ScrollView android:layout_width="fill_parent"
- android:layout_height="0dip" android:layout_weight="1"
- android:scrollbarStyle="outsideInset"
- android:fillViewport="true">
- <LinearLayout android:orientation="vertical"
- android:layout_width="fill_parent" android:layout_height="wrap_content">
- <LinearLayout android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" android:background="#ededed">
- <MultiAutoCompleteTextView
- android:id="@+id/to" android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorSecondaryInverse"
- android:layout_marginLeft="6px"
- android:layout_marginRight="6px"
- android:inputType="textEmailAddress|textMultiLine"
- android:hint="@string/message_compose_to_hint" />
- <MultiAutoCompleteTextView
- android:id="@+id/cc" android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorSecondaryInverse"
- android:layout_marginLeft="6px"
- android:layout_marginRight="6px"
- android:inputType="textEmailAddress|textMultiLine"
- android:hint="@string/message_compose_cc_hint"
- android:visibility="gone" />
- <MultiAutoCompleteTextView
- android:id="@+id/bcc" android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorSecondaryInverse"
- android:layout_marginLeft="6px"
- android:layout_marginRight="6px"
- android:inputType="textEmailAddress|textMultiLine"
- android:hint="@string/message_compose_bcc_hint"
- android:visibility="gone" />
- <EditText android:id="@+id/subject"
- android:layout_width="fill_parent"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_height="wrap_content"
- android:textColor="?android:attr/textColorSecondaryInverse"
- android:layout_marginLeft="6px"
- android:layout_marginRight="6px"
- android:hint="@string/message_compose_subject_hint"
- android:inputType="textEmailSubject|textAutoCorrect|textCapSentences|textImeMultiLine" />
- <!--
- Empty container for storing attachments. We'll stick
- instances of message_compose_attachment.xml in here.
- -->
- <LinearLayout android:id="@+id/attachments"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" />
- <View android:layout_width="fill_parent"
- android:layout_height="1px"
- android:background="@drawable/divider_horizontal_email" />
- </LinearLayout>
- <EditText android:id="@+id/message_content"
- android:textColor="?android:attr/textColorSecondaryInverse"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1.0"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:gravity="left|top"
- android:minLines="3"
- android:inputType="textMultiLine|textAutoCorrect|textCapSentences" />
- <!-- quoted text bar -->
- <RelativeLayout android:id="@+id/quoted_text_bar"
- android:layout_width="fill_parent"
- android:layout_height="45px" android:background="@drawable/email_quoted_bar">
- <TextView android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorSecondaryInverse"
- android:text="@string/message_compose_quoted_text_label"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true" />
- <ImageButton android:id="@+id/quoted_text_delete"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@android:drawable/btn_dialog"
- android:layout_centerVertical="true"
- android:layout_alignParentRight="true" />
- </RelativeLayout>
- <WebView android:id="@+id/quoted_text"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent" />
- </LinearLayout>
- </ScrollView>
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingTop="5dip"
- android:paddingLeft="4dip"
- android:paddingRight="4dip"
- android:paddingBottom="1dip"
- android:background="@android:drawable/bottom_bar" >
- <Button
- android:id="@+id/send"
- android:text="@string/send_action"
- android:layout_height="fill_parent"
- android:layout_width="0dip"
- android:layout_weight="1" />
- <Button
- android:id="@+id/save"
- android:text="@string/save_draft_action"
- android:layout_height="fill_parent"
- android:layout_width="0dip"
- android:layout_weight="1" />
- <Button
- android:id="@+id/discard"
- android:text="@string/discard_action"
- android:layout_height="fill_parent"
- android:layout_width="0dip"
- android:layout_weight="1" />
- </LinearLayout>
-</LinearLayout>
diff --git a/res/layout/message_compose_attachment.xml b/res/layout/message_compose_attachment.xml
deleted file mode 100644
index 61c481eaa..000000000
--- a/res/layout/message_compose_attachment.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="54px"
- android:paddingRight="6px"
- android:paddingTop="6px"
- android:paddingBottom="6px">
- <ImageButton
- android:id="@+id/attachment_delete"
- android:src="@android:drawable/ic_delete"
- android:layout_alignParentRight="true"
- android:layout_height="42px"
- android:layout_width="42px" />
- <TextView
- android:id="@+id/attachment_name"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorSecondaryInverse"
- android:layout_width="1dip"
- android:layout_height="42px"
- android:background="@drawable/text_box"
- android:paddingLeft="36px"
- android:singleLine="true"
- android:ellipsize="start"
- android:gravity="center_vertical"
- android:layout_marginLeft="6px"
- android:layout_marginRight="4px"
- android:layout_alignParentLeft="true"
- android:layout_toLeftOf="@id/attachment_delete" />
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_email_attachment"
- android:layout_marginLeft="1px"
- android:layout_centerVertical="true" />
-</RelativeLayout>
diff --git a/res/layout/message_view.xml b/res/layout/message_view.xml
deleted file mode 100644
index 9f1e3f8fa..000000000
--- a/res/layout/message_view.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="@android:color/white">
- <ScrollView
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:scrollbarStyle="outsideInset"
- android:fadingEdge="none">
- <LinearLayout
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1">
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="54px"
- android:paddingTop="4px">
- <Button
- android:id="@+id/previous"
- android:text="@string/message_view_prev_action"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:minWidth="@dimen/button_minWidth"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true" />
- <Button
- android:id="@+id/next"
- android:text="@string/message_view_next_action"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:minWidth="@dimen/button_minWidth"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true" />
- </RelativeLayout>
-
- <include layout="@layout/message_view_header" />
-
- </LinearLayout>
- </ScrollView>
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingTop="5dip"
- android:paddingLeft="4dip"
- android:paddingRight="4dip"
- android:paddingBottom="1dip"
- android:background="@android:drawable/bottom_bar">
- <Button
- android:id="@+id/reply"
- android:text="@string/reply_action"
- android:layout_height="fill_parent"
- android:layout_width="0dip"
- android:layout_weight="1" />
- <Button
- android:id="@+id/reply_all"
- android:text="@string/reply_all_action"
- android:layout_height="fill_parent"
- android:layout_width="0dip"
- android:layout_weight="1" />
- <Button
- android:id="@+id/delete"
- android:text="@string/delete_action"
- android:layout_height="fill_parent"
- android:layout_width="0dip"
- android:layout_weight="1" />
- </LinearLayout>
-</LinearLayout>
diff --git a/res/layout/message_view_attachment.xml b/res/layout/message_view_attachment.xml
deleted file mode 100644
index 83d9ec9d8..000000000
--- a/res/layout/message_view_attachment.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="4px">
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingLeft="4px">
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:background="@drawable/text_box"
- android:gravity="center_vertical">
- <ImageView
- android:id="@+id/attachment_icon"
- android:layout_width="62px"
- android:layout_height="62px"
- android:src="@drawable/attached_image_placeholder"
- android:layout_marginLeft="4px"
- android:layout_marginRight="4px"
- android:layout_marginBottom="4px"
- android:layout_marginTop="4px" />
- <TextView
- android:id="@+id/attachment_name"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorSecondaryInverse"
- android:singleLine="true"
- android:ellipsize="middle"
- android:layout_alignParentTop="true"
- android:layout_toRightOf="@id/attachment_icon"
- android:layout_alignParentRight="true"
- android:layout_alignWithParentIfMissing="true" />
- <TextView
- android:id="@+id/attachment_info"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorTertiaryInverse"
- android:singleLine="true"
- android:ellipsize="middle"
- android:layout_alignLeft="@id/attachment_name"
- android:layout_below="@id/attachment_name"
- android:layout_alignWithParentIfMissing="true" />
- <Button
- android:id="@+id/download"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- style="?android:attr/buttonStyleSmall"
- android:text="@string/message_view_attachment_download_action"
- android:singleLine="true"
- android:layout_alignParentRight="true"
- android:layout_below="@id/attachment_name"
- android:layout_marginTop="6px" />
- <Button
- android:id="@+id/view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- style="?android:attr/buttonStyleSmall"
- android:text="@string/message_view_attachment_view_action"
- android:singleLine="true"
- android:layout_toLeftOf="@id/download"
- android:layout_alignWithParentIfMissing="true"
- android:layout_below="@id/attachment_name"
- android:layout_marginTop="6px" />
- </RelativeLayout>
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_gravity="center_vertical">
- <ImageView
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:src="@drawable/ic_email_attachment"
- android:layout_alignParentLeft="true" />
- </LinearLayout>
-</FrameLayout>
diff --git a/res/layout/message_view_header.xml b/res/layout/message_view_header.xml
deleted file mode 100644
index d414a189d..000000000
--- a/res/layout/message_view_header.xml
+++ /dev/null
@@ -1,157 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <!-- header area -->
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:background="@drawable/ic_email_thread_open_top_default">
- <LinearLayout
- android:id="@+id/from_container"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
- <TextView
- android:id="@+id/from"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorPrimaryInverse"
- android:layout_width="0dip"
- android:layout_weight="1.0"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:singleLine="true"
- android:ellipsize="end"
- android:paddingRight="6px" />
- <View
- android:id="@+id/attachment"
- android:background="@drawable/ic_email_attachment_small"
- android:layout_width="22px"
- android:layout_height="22px"
- android:layout_alignTop="@id/from" />
- <TextView
- android:id="@+id/date"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimaryInverse"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="4px"
- android:singleLine="true" />
- </LinearLayout>
- <LinearLayout
- android:id="@+id/to_container"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
- <TextView
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondaryInverse"
- android:textStyle="bold"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/message_view_to_label" />
- <TextView
- android:id="@+id/to"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondaryInverse"
- android:layout_width="0dip"
- android:layout_weight="1.0"
- android:layout_height="wrap_content"
- android:layout_marginLeft="4px"
- android:singleLine="false"
- android:ellipsize="none" />
- <TextView
- android:id="@+id/time"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimaryInverse"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="4px"
- android:singleLine="true" />
- </LinearLayout>
- <LinearLayout
- android:id="@+id/cc_container"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
- <TextView
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondaryInverse"
- android:textStyle="bold"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/message_view_cc_label" />
- <TextView
- android:id="@+id/cc"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondaryInverse"
- android:layout_width="0dip"
- android:layout_weight="1.0"
- android:layout_height="wrap_content"
- android:layout_marginLeft="4px"
- android:singleLine="false"
- android:ellipsize="none" />
- </LinearLayout>
- <TextView
- android:id="@+id/subject"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondaryInverse"
- android:textStyle="bold"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:singleLine="false"
- android:ellipsize="none" />
- </LinearLayout>
- <LinearLayout
- android:id="@+id/show_pictures_section"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:background="#ffefefef"
- android:layout_marginTop="6dip"
- android:paddingLeft="6dip"
- android:paddingRight="3dip"
- android:paddingTop="4dip"
- android:paddingBottom="4dip"
- android:baselineAligned="false"
- android:visibility="gone">
- <TextView
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondaryInverse"
- android:text="@string/message_view_show_pictures_instructions"
- android:layout_gravity="center"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1.0" />
- <Button
- android:id="@+id/show_pictures"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/message_view_show_pictures_action" />
- </LinearLayout>
- <!-- content area -->
- <WebView
- android:id="@+id/message_content"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:background="#ffffff" />
- <!-- attachments area -->
- <LinearLayout
- android:id="@+id/attachments"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:padding="4dip"
- android:background="#ffffff">
- </LinearLayout>
-</merge>
diff --git a/res/layout/recipient_dropdown_item.xml b/res/layout/recipient_dropdown_item.xml
deleted file mode 100644
index 4e2dca1f4..000000000
--- a/res/layout/recipient_dropdown_item.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="50px"
- android:orientation="horizontal">
- <TextView android:id="@+id/text1"
- android:textColor="?android:attr/textColorPrimaryInverse"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:paddingLeft="6px"
- android:singleLine="true"
- android:ellipsize="end"
- />
- <TextView android:id="@+id/text2"
- android:textColor="?android:attr/textColorSecondaryInverse"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/text1"
- android:layout_centerVertical="true"
- android:paddingLeft="6px"
- android:singleLine="true"
- android:ellipsize="end"
- />
- </RelativeLayout>
diff --git a/res/menu/accounts_context.xml b/res/menu/accounts_context.xml
deleted file mode 100644
index f950791aa..000000000
--- a/res/menu/accounts_context.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@+id/open"
- android:title="@string/open_action" />
- <item android:id="@+id/edit_account"
- android:title="@string/account_settings_action" />
- <item android:id="@+id/delete_account"
- android:title="@string/remove_account_action" />
-</menu>
diff --git a/res/menu/accounts_option.xml b/res/menu/accounts_option.xml
deleted file mode 100644
index 37a0f2364..000000000
--- a/res/menu/accounts_option.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/check_mail"
- android:alphabeticShortcut="r"
- android:title="@string/refresh_action"
- android:icon="@*android:drawable/ic_menu_refresh"
- />
- <item
- android:id="@+id/add_new_account"
- android:title="@string/add_account_action"
- android:icon="@android:drawable/ic_menu_add"
- />
- <item
- android:id="@+id/compose"
- android:alphabeticShortcut="c"
- android:title="@string/compose_action"
- android:icon="@*android:drawable/ic_menu_compose"
- />
- <!--
- <item android:id="@+id/search"
- android:title="@string/search_action" />
- <item android:id="@+id/preferences"
- android:title="@string/preferences_action" />
- -->
-</menu>
diff --git a/res/menu/debug_option.xml b/res/menu/debug_option.xml
deleted file mode 100644
index 5a31fe504..000000000
--- a/res/menu/debug_option.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@+id/dump_settings"
- android:title="@string/dump_settings_action" />
-</menu>
diff --git a/res/menu/folder_message_list_context.xml b/res/menu/folder_message_list_context.xml
deleted file mode 100644
index 051f7f7cc..000000000
--- a/res/menu/folder_message_list_context.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/open"
- android:title="@string/open_action"
- />
- <item
- android:id="@+id/delete"
- android:title="@string/delete_action"
- />
- <item
- android:id="@+id/forward"
- android:title="@string/forward_action"
- />
- <item
- android:id="@+id/reply_all"
- android:title="@string/reply_all_action"
- />
- <item
- android:id="@+id/reply"
- android:title="@string/reply_action"
- />
- <item
- android:id="@+id/mark_as_read"
- android:title="@string/mark_as_read_action"
- />
-</menu>
diff --git a/res/menu/folder_message_list_option.xml b/res/menu/folder_message_list_option.xml
deleted file mode 100644
index 5ea8780b5..000000000
--- a/res/menu/folder_message_list_option.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/refresh"
- android:alphabeticShortcut="r"
- android:title="@string/refresh_action"
- android:icon="@*android:drawable/ic_menu_refresh"
-
- />
- <item
- android:id="@+id/compose"
- android:alphabeticShortcut="c"
- android:title="@string/compose_action"
- android:icon="@*android:drawable/ic_menu_compose"
- />
- <item
- android:id="@+id/accounts"
- android:title="@string/accounts_action"
- android:icon="@*android:drawable/ic_menu_account_list"
- />
- <item
- android:id="@+id/account_settings"
- android:title="@string/account_settings_action"
- android:icon="@android:drawable/ic_menu_preferences"
- />
- <!--
- <item android:id="@+id/search"
- android:title="@string/search_action" />
- <item android:id="@+id/preferences"
- android:title="@string/preferences_action" />
- -->
-</menu>
diff --git a/res/menu/message_compose_option.xml b/res/menu/message_compose_option.xml
deleted file mode 100644
index 521b66b0a..000000000
--- a/res/menu/message_compose_option.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/add_cc_bcc"
- android:alphabeticShortcut="c"
- android:title="@string/add_cc_bcc_action"
- android:icon="@*android:drawable/ic_menu_cc"
- />
- <item
- android:id="@+id/send"
- android:alphabeticShortcut="s"
- android:title="@string/send_action"
- android:icon="@android:drawable/ic_menu_send"
- />
- <item
- android:id="@+id/save"
- android:alphabeticShortcut="d"
- android:title="@string/save_draft_action"
- android:icon="@drawable/ic_menu_save_draft"
- />
- <item
- android:id="@+id/discard"
- android:alphabeticShortcut="q"
- android:title="@string/discard_action"
- android:icon="@android:drawable/ic_menu_close_clear_cancel"
- />
- <item
- android:id="@+id/add_attachment"
- android:alphabeticShortcut="n"
- android:title="@string/add_attachment_action"
- android:icon="@*android:drawable/ic_menu_attachment"
- />
-</menu>
diff --git a/res/menu/message_view_option.xml b/res/menu/message_view_option.xml
deleted file mode 100644
index 7807a8b8b..000000000
--- a/res/menu/message_view_option.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/delete"
- android:alphabeticShortcut="q"
- android:title="@string/delete_action"
- android:icon="@android:drawable/ic_menu_delete"
- />
- <item
- android:id="@+id/forward"
- android:alphabeticShortcut="f"
- android:title="@string/forward_action"
- android:icon="@drawable/ic_menu_forward_mail"
- />
- <item
- android:id="@+id/reply"
- android:alphabeticShortcut="r"
- android:title="@string/reply_action"
- android:icon="@drawable/ic_menu_reply"
- />
- <item
- android:id="@+id/reply_all"
- android:alphabeticShortcut="a"
- android:title="@string/reply_all_action"
- android:icon="@drawable/ic_menu_reply_all"
- />
- <item
- android:id="@+id/mark_as_unread"
- android:alphabeticShortcut="u"
- android:title="@string/mark_as_unread_action"
- android:icon="@*android:drawable/ic_menu_mark"
- />
-</menu>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
deleted file mode 100644
index 7067bdff7..000000000
--- a/res/values-cs/strings.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="read_attachment_label">"pÅ™eÄíst přílohy e-mailu"</string>
- <string name="read_attachment_desc">"Umožňuje této aplikaci Ätení e-mailových příloh."</string>
- <string name="app_name">"E-mail"</string>
- <string name="accounts_title">"VaÅ¡e úÄty"</string>
- <string name="compose_title">"Nová"</string>
- <string name="debug_title">"Ladění"</string>
- <string name="next_action">"Další"</string>
- <string name="okay_action">"OK"</string>
- <string name="cancel_action">"Zrušit"</string>
- <string name="send_action">"Odeslat"</string>
- <string name="reply_action">"Odpovědět"</string>
- <string name="reply_all_action">"Odpovědět všem"</string>
- <string name="delete_action">"Smazat"</string>
- <string name="forward_action">"Přeposlat"</string>
- <string name="done_action">"Hotovo"</string>
- <string name="discard_action">"Zrušit"</string>
- <string name="save_draft_action">"Uložit jako koncept"</string>
- <string name="refresh_action">"Obnovit"</string>
- <string name="add_account_action">"PÅ™idat úÄet"</string>
- <string name="compose_action">"Nová"</string>
- <string name="search_action">"Hledat"</string>
- <string name="open_action">"Otevřít"</string>
- <string name="account_settings_action">"Nastavení úÄtu"</string>
- <string name="remove_account_action">"Odebrat úÄet"</string>
- <string name="accounts_action">"ÚÄty"</string>
- <string name="mark_as_read_action">"OznaÄit jako pÅ™eÄtené"</string>
- <string name="mark_as_unread_action">"OznaÄit jako nepÅ™eÄtené"</string>
- <string name="add_cc_bcc_action">"Přidat příjemce kopie/skryté kopie"</string>
- <string name="add_attachment_action">"Připojit přílohu"</string>
- <string name="dump_settings_action">"Nastavení výpisu"</string>
- <string name="accounts_context_menu_title">"Možnosti úÄtu"</string>
- <string name="status_loading_more">"NaÄítání zpráv..."</string>
- <string name="status_network_error">"Chyba připojení"</string>
- <string name="status_loading_more_failed">"Opakovat naÄítání dalších zpráv"</string>
- <string name="notification_new_title">"Nový e-mail"</string>
- <string name="notification_new_one_account_fmt">"NepÅ™eÄtené zprávy: <xliff:g id="UNREAD_MESSAGE_COUNT">%d</xliff:g>(<xliff:g id="ACCOUNT">%s</xliff:g>)"</string>
- <string name="notification_new_multi_account_fmt">"v(e) <xliff:g id="NUMBER_ACCOUNTS">%d</xliff:g> úÄtech"</string>
- <string name="special_mailbox_name_inbox">"DoruÄená poÅ¡ta"</string>
- <string name="accounts_welcome">"Vítá vás nastavení aplikace Email!"\n\n"V aplikaci Email můžete používat jakékoli e-mailové úÄty."\n\n"NejznámÄ›jší e-mailové úÄty lze nastavit ve dvou krocích!"</string>
- <string name="debug_version_fmt">"Verze: <xliff:g id="VERSION">%s</xliff:g>"</string>
- <string name="debug_enable_debug_logging_label">"Povolit zvláštní protokolování ladění?"</string>
- <string name="debug_enable_sensitive_logging_label">"Povolit protokolování ladění citlivých informací? (Může zobrazovat hesla v protokolech.)"</string>
- <string name="message_list_load_more_messages_action">"NaÄíst další zprávy"</string>
- <string name="message_compose_to_hint">"Komu"</string>
- <string name="message_compose_cc_hint">"Kopie"</string>
- <string name="message_compose_bcc_hint">"Skrytá kopie"</string>
- <string name="message_compose_subject_hint">"Předmět"</string>
- <string name="message_compose_fwd_header_fmt">\n\n"-------- Původní zpráva --------"\n"Předmět: <xliff:g id="SUBJECT">%s</xliff:g>"\n"Odesílatel: <xliff:g id="SENDER">%s</xliff:g>"\n"Komu: <xliff:g id="TO">%s</xliff:g>"\n"Kopie: <xliff:g id="CC_0">%s</xliff:g>"\n\n</string>
- <string name="message_compose_reply_header_fmt">\n\n"<xliff:g id="SENDER">%s</xliff:g>napsal/a:"\n\n</string>
- <string name="message_compose_quoted_text_label">"Text v uvozovkách"</string>
- <string name="message_compose_error_no_recipients">"Je třeba přidat nejméně jednoho příjemce."</string>
- <string name="message_compose_attachments_skipped_toast">"Některé přílohy nelze přeposlat, protože nebyly staženy."</string>
- <string name="message_view_to_label">"Komu:"</string>
- <string name="message_view_cc_label">"Kopie:"</string>
- <string name="message_view_attachment_view_action">"Otevřít"</string>
- <string name="message_view_attachment_download_action">"Uložit"</string>
- <string name="message_view_prev_action">"Náhled zprávy"</string>
- <string name="message_view_next_action">"Další zpráva"</string>
- <string name="message_view_status_attachment_saved">"Příloha byla uložena na SD kartu jako <xliff:g id="FILENAME">%s</xliff:g>."</string>
- <string name="message_view_status_attachment_not_saved">"Nelze uložit přílohu na SD kartu."</string>
- <string name="message_view_show_pictures_instructions">"Výběrem možnosti Zobrazit obrázky zobrazíte vnořené obrázky."</string>
- <string name="message_view_show_pictures_action">"Zobrazit obrázky"</string>
- <string name="message_view_fetching_attachment_toast">"NaÄítání přílohy"</string>
- <string name="message_deleted_toast">"Zpráva byla smazána."</string>
- <string name="message_discarded_toast">"Zpráva byla zrušena."</string>
- <string name="message_saved_toast">"Zpráva byla uložena jako koncept."</string>
- <string name="account_setup_basics_title">"Nastavit e-mail"</string>
- <string name="account_setup_basics_instructions">"Zadejte e-mailovou adresu úÄtu:"</string>
- <string name="account_setup_basics_email_hint">"E-mailová adresa"</string>
- <string name="account_setup_basics_password_hint">"Heslo"</string>
- <string name="account_setup_basics_default_label">"Ve výchozím nastavení odesílat e-maily z tohoto úÄtu."</string>
- <string name="account_setup_basics_manual_setup_action">"RuÄní nastavení"</string>
- <string name="account_setup_username_password_toast">"Zadejte platnou e-mailovou adresu a heslo."</string>
- <string name="account_setup_check_settings_retr_info_msg">"NaÄítání informací o úÄtu..."</string>
- <string name="account_setup_check_settings_check_incoming_msg">"Kontrola nastavení serveru příchozí pošty..."</string>
- <string name="account_setup_check_settings_check_outgoing_msg">"Kontrola nastavení serveru odchozí pošty..."</string>
- <string name="account_setup_check_settings_canceling_msg">"Probíhá zrušení..."</string>
- <string name="account_setup_names_title">"Nastavit e-mail"</string>
- <string name="account_setup_names_instructions">"Váš úÄet je nastaven, e-mail je na cestÄ›!"</string>
- <string name="account_setup_names_account_name_label">"Pojmenovat tento úÄet (nepovinné)"</string>
- <string name="account_setup_names_user_name_label">"Vaše jméno (zobrazované v odchozích zprávách)"</string>
- <string name="account_setup_account_type_title">"PÅ™idat nový e-mailový úÄet"</string>
- <string name="account_setup_account_type_instructions">"O jaký typ úÄtu se jedná?"</string>
- <string name="account_setup_account_type_pop_action">"ÚÄet POP3"</string>
- <string name="account_setup_account_type_imap_action">"ÚÄet IMAP"</string>
- <string name="account_setup_incoming_title">"Nastavení serveru příchozí pošty"</string>
- <string name="account_setup_incoming_username_label">"Uživatelské jméno"</string>
- <string name="account_setup_incoming_password_label">"Heslo"</string>
- <string name="account_setup_incoming_pop_server_label">"Server POP"</string>
- <string name="account_setup_incoming_imap_server_label">"Server IMAP"</string>
- <string name="account_setup_incoming_port_label">"Port"</string>
- <string name="account_setup_incoming_security_label">"Typ zabezpeÄení"</string>
- <string name="account_setup_incoming_security_none_label">"Nic"</string>
- <string name="account_setup_incoming_security_ssl_optional_label">"SSL (pokud je k dispozici)"</string>
- <string name="account_setup_incoming_security_ssl_label">"SSL (vždy)"</string>
- <string name="account_setup_incoming_security_tls_optional_label">"TLS (je-li k dispozici)"</string>
- <string name="account_setup_incoming_security_tls_label">"TLS (vždy)"</string>
- <string name="account_setup_incoming_delete_policy_label">"Odstranit e-mail ze serveru"</string>
- <string name="account_setup_incoming_delete_policy_never_label">"Nikdy"</string>
- <string name="account_setup_incoming_delete_policy_7days_label">"Po 7 dnech"</string>
- <string name="account_setup_incoming_delete_policy_delete_label">"PÅ™i odstranÄ›ní ze složky DoruÄená poÅ¡ta"</string>
- <string name="account_setup_incoming_imap_path_prefix_label">"Předpona cesty IMAP"</string>
- <string name="account_setup_incoming_imap_path_prefix_hint">"Nepovinné"</string>
- <string name="account_setup_outgoing_title">"Nastavení odchozího serveru"</string>
- <string name="account_setup_outgoing_smtp_server_label">"Server SMTP"</string>
- <string name="account_setup_outgoing_port_label">"Port"</string>
- <string name="account_setup_outgoing_security_label">"Typ zabezpeÄení"</string>
- <string name="account_setup_outgoing_require_login_label">"Požadovat přihlášení"</string>
- <string name="account_setup_outgoing_username_label">"Uživatelské jméno"</string>
- <string name="account_setup_outgoing_password_label">"Heslo"</string>
- <string name="account_setup_options_title">"Možnosti úÄtu"</string>
- <string name="account_setup_options_mail_check_frequency_label">"Četnost kontrol e-mailů"</string>
- <string name="account_setup_options_mail_check_frequency_never">"Nikdy"</string>
- <string name="account_setup_options_mail_check_frequency_5min">"Každých 5 minut"</string>
- <string name="account_setup_options_mail_check_frequency_10min">"Každých 10 minut"</string>
- <string name="account_setup_options_mail_check_frequency_15min">"Každých 15 minut"</string>
- <string name="account_setup_options_mail_check_frequency_30min">"Každých 30 minut"</string>
- <string name="account_setup_options_mail_check_frequency_1hour">"Každou hodinu"</string>
- <string name="account_setup_options_default_label">"Ve výchozím nastavení odesílat e-maily z tohoto úÄtu."</string>
- <string name="account_setup_options_notify_label">"Upozornit mě na příchod e-mailu"</string>
- <string name="account_setup_failed_dlg_title">"Nastavení nelze dokonÄit"</string>
- <string name="account_setup_failed_dlg_auth_message">"Uživatelské jméno nebo heslo není správné"</string>
- <string name="account_setup_failed_dlg_auth_message_fmt">"Uživatelské jméno nebo heslo není správné."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_certificate_message">"Nelze se bezpeÄnÄ› pÅ™ipojit k serveru."</string>
- <string name="account_setup_failed_dlg_certificate_message_fmt">"Nelze se bezpeÄnÄ› pÅ™ipojit k serveru."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_server_message">"Nelze se připojit k serveru."</string>
- <string name="account_setup_failed_dlg_server_message_fmt">"Nelze se připojit k serveru."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_tls_required">"Služba TLS je požadována, ale není podporována na serveru."</string>
- <string name="account_setup_failed_auth_required">"Server nepodporuje metody ověření."</string>
- <string name="account_setup_failed_security">"Nelze navázat pÅ™ipojení k serveru z důvodu chyby zabezpeÄení."</string>
- <string name="account_setup_failed_ioerror">"Nelze navázat připojení k serveru."</string>
- <string name="account_setup_failed_dlg_edit_details_action">"Upravit podrobnosti"</string>
- <string name="account_settings_title_fmt">"Obecná nastavení"</string>
- <string name="account_settings_default_label">"Výchozí úÄet"</string>
- <string name="account_settings_default_summary">"Ve výchozím nastavení odesílat e-maily z tohoto úÄtu"</string>
- <string name="account_settings_notify_label">"E-mailová upozornění"</string>
- <string name="account_settings_notify_summary">"Zobrazit upozornění na příchod e-mailu na stavovém řádku"</string>
- <string name="account_settings_mail_check_frequency_label">"Četnost kontrol e-mailů"</string>
- <string name="account_settings_incoming_label">"Nastavení příchozí pošty"</string>
- <string name="account_settings_outgoing_label">"Nastavení odchozí pošty"</string>
- <string name="account_settings_add_account_label">"PÅ™idat další úÄet"</string>
- <string name="account_settings_description_label">"Název úÄtu"</string>
- <string name="account_settings_name_label">"Vaše jméno"</string>
- <string name="account_settings_notifications">"Nastavení upozornění"</string>
- <string name="account_settings_vibrate_enable">"Vibrovat"</string>
- <string name="account_settings_vibrate_summary">"Při příchodu e-mailu také vibrovat"</string>
- <string name="account_settings_ringtone">"Zvolit vyzváněcí tón"</string>
- <string name="account_settings_servers">"Nastavení serveru"</string>
- <string name="account_delete_dlg_title">"Odebrat úÄet"</string>
- <string name="account_delete_dlg_instructions_fmt">"ÚÄet <xliff:g id="ACCOUNT">%s</xliff:g> bude z aplikace Email odebrán."</string>
- <string name="provider_note_yahoo">"Přístup do schránky není u nÄ›kterých poÅ¡tovních úÄtů Yahoo! podporován. Pokud máte problémy s pÅ™ipojením, získáte další informace na webové stránce yahoo.com."</string>
- <string name="provider_note_yahoo_uk">"PÅ™ed nastavením tohoto e-mailového úÄtu pÅ™ejdÄ›te na web Yahoo! a povolte u tohoto úÄtu e-mailový přístup POP3."</string>
- <string name="provider_note_live">"Pouze nÄ›které úÄty typu Plus obsahují přístup POP umožňující pÅ™ipojení tohoto programu. Pokud se nemůžete pÅ™ihlásit se správnou e-mailovou adresou a heslem, pravdÄ›podobnÄ› nemáte placený úÄet Plus. SpusÅ¥te webový prohlížeÄ a vyhledejte přístup k tÄ›mto poÅ¡tovním úÄtům."</string>
- <string name="provider_note_t_online">"PÅ™ed nastavením tohoto e-mailového úÄtu navÅ¡tivte web T-Online a vytvoÅ™te heslo pro e-mailový přístup POP3."</string>
-</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
deleted file mode 100644
index 823ca36b4..000000000
--- a/res/values-de/strings.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="read_attachment_label">"Anhänge lesen"</string>
- <string name="read_attachment_desc">"Erlaubt der Anwendung, Ihre Anhänge zu lesen."</string>
- <string name="app_name">"E-Mail"</string>
- <string name="accounts_title">"Ihre Konten"</string>
- <string name="compose_title">"E-Mail schreiben"</string>
- <string name="debug_title">"Fehlersuche"</string>
- <string name="next_action">"Weiter"</string>
- <string name="okay_action">"OK"</string>
- <string name="cancel_action">"Abbrechen"</string>
- <string name="send_action">"Senden"</string>
- <string name="reply_action">"Antworten"</string>
- <string name="reply_all_action">"Allen antworten"</string>
- <string name="delete_action">"Löschen"</string>
- <string name="forward_action">"Weiterleiten"</string>
- <string name="done_action">"Fertig"</string>
- <string name="discard_action">"Löschen"</string>
- <string name="save_draft_action">"Als Entwurf speichern"</string>
- <string name="refresh_action">"Aktualisieren"</string>
- <string name="add_account_action">"Konto hinzufügen"</string>
- <string name="compose_action">"E-Mail schreiben"</string>
- <string name="search_action">"Suchen"</string>
- <string name="open_action">"Öffnen"</string>
- <string name="account_settings_action">"Kontoeinstellungen"</string>
- <string name="remove_account_action">"Konto entfernen"</string>
- <string name="accounts_action">"Konten"</string>
- <string name="mark_as_read_action">"Als gelesen markieren"</string>
- <string name="mark_as_unread_action">"Als ungelesen markieren"</string>
- <string name="add_cc_bcc_action">"Feld \"Cc\"/\"Bcc\" hinzufügen"</string>
- <string name="add_attachment_action">"Anhang hinzufügen"</string>
- <string name="dump_settings_action">"Einstellungen für Speicherauszug"</string>
- <string name="accounts_context_menu_title">"Kontooptionen"</string>
- <string name="status_loading_more">"Nachrichten werden geladen..."</string>
- <string name="status_network_error">"Verbindungsfehler"</string>
- <string name="status_loading_more_failed">"Laden weiterer Nachrichten erneut versuchen"</string>
- <string name="notification_new_title">"Neue E-Mail"</string>
- <string name="notification_new_one_account_fmt">"<xliff:g id="UNREAD_MESSAGE_COUNT">%d</xliff:g> ungelesen (<xliff:g id="ACCOUNT">%s</xliff:g>)"</string>
- <string name="notification_new_multi_account_fmt">"in <xliff:g id="NUMBER_ACCOUNTS">%d</xliff:g> Google-Konten"</string>
- <string name="special_mailbox_name_inbox">"Posteingang"</string>
- <string name="accounts_welcome">"Willkommen bei der Einrichtung von E-Mails."\n\n"Nutzen Sie ein beliebiges E-Mail-Konto."\n\n"Gängige E-Mail-Konten können in nur zwei Schritten eingerichtet werden."</string>
- <string name="debug_version_fmt">"Version: <xliff:g id="VERSION">%s</xliff:g>"</string>
- <string name="debug_enable_debug_logging_label">"Zusätzliche Debug-Protokollierung aktivieren?"</string>
- <string name="debug_enable_sensitive_logging_label">"Debug-Protokoll für sensible Daten aktivieren? (Passwörter werden evtl. in Protokollen angezeigt.)"</string>
- <string name="message_list_load_more_messages_action">"Weitere Nachrichten laden"</string>
- <string name="message_compose_to_hint">"An"</string>
- <string name="message_compose_cc_hint">"Cc"</string>
- <string name="message_compose_bcc_hint">"Bcc"</string>
- <string name="message_compose_subject_hint">"Betreff"</string>
- <string name="message_compose_fwd_header_fmt">\n\n"-------- Originalnachricht --------"\n"Betreff: <xliff:g id="SUBJECT">%s</xliff:g>"\n"Von: <xliff:g id="SENDER">%s</xliff:g>"\n"An: <xliff:g id="TO">%s</xliff:g>"\n"Cc: <xliff:g id="CC_0">%s</xliff:g>"\n\n</string>
- <string name="message_compose_reply_header_fmt">\n\n"<xliff:g id="SENDER">%s</xliff:g> schrieb:"\n\n</string>
- <string name="message_compose_quoted_text_label">"Zitierter Text"</string>
- <string name="message_compose_error_no_recipients">"Sie müssen mindestens einen Empfänger hinzufügen."</string>
- <string name="message_compose_attachments_skipped_toast">"Einige Anhänge können nicht weitergeleitet werden, da Sie noch nicht heruntergeladen wurden."</string>
- <string name="message_view_to_label">"An:"</string>
- <string name="message_view_cc_label">"Cc:"</string>
- <string name="message_view_attachment_view_action">"Öffnen"</string>
- <string name="message_view_attachment_download_action">"Speichern"</string>
- <string name="message_view_prev_action">"Vorherige Nachricht"</string>
- <string name="message_view_next_action">"Nächste Nachricht"</string>
- <string name="message_view_status_attachment_saved">"Anhang auf SD-Speicherkarte unter \"<xliff:g id="FILENAME">%s</xliff:g>\" abgespeichert"</string>
- <string name="message_view_status_attachment_not_saved">"Speichern des Anhangs auf SD-Karte nicht möglich"</string>
- <string name="message_view_show_pictures_instructions">"Wählen Sie \"Bilder anzeigen\" aus, um eingebettete Bilder anzuzeigen."</string>
- <string name="message_view_show_pictures_action">"Bilder anzeigen"</string>
- <string name="message_view_fetching_attachment_toast">"Anhang wird abgerufen"</string>
- <string name="message_deleted_toast">"Nachricht gelöscht"</string>
- <string name="message_discarded_toast">"Nachricht gelöscht"</string>
- <string name="message_saved_toast">"Nachricht als Entwurf gespeichert"</string>
- <string name="account_setup_basics_title">"E-Mail einrichten"</string>
- <string name="account_setup_basics_instructions">"Geben Sie Ihre im Konto gespeicherte E-Mail-Adresse ein:"</string>
- <string name="account_setup_basics_email_hint">"E-Mail-Adresse"</string>
- <string name="account_setup_basics_password_hint">"Passwort"</string>
- <string name="account_setup_basics_default_label">"E-Mails standardmäßig von diesem Konto senden"</string>
- <string name="account_setup_basics_manual_setup_action">"Manuelle Einrichtung"</string>
- <string name="account_setup_username_password_toast">"Geben Sie eine gültige E-Mail-Adresse und ein gültiges Passwort ein."</string>
- <string name="account_setup_check_settings_retr_info_msg">"Kontoinformationen werden abgerufen..."</string>
- <string name="account_setup_check_settings_check_incoming_msg">"Einstellungen des Eingangsservers werden überprüft..."</string>
- <string name="account_setup_check_settings_check_outgoing_msg">"Einstellungen des Ausgangsservers werden überprüft..."</string>
- <string name="account_setup_check_settings_canceling_msg">"Vorgang wird abgebrochen..."</string>
- <string name="account_setup_names_title">"E-Mail einrichten"</string>
- <string name="account_setup_names_instructions">"Ihr Konto ist nun eingerichtet."</string>
- <string name="account_setup_names_account_name_label">"Konto benennen (optional)"</string>
- <string name="account_setup_names_user_name_label">"Ihr Name (wird für ausgehende Nachrichten angezeigt)"</string>
- <string name="account_setup_account_type_title">"Neues E-Mail-Konto hinzufügen"</string>
- <string name="account_setup_account_type_instructions">"Um welchen Kontotyp handelt es sich hierbei?"</string>
- <string name="account_setup_account_type_pop_action">"POP3-Konto"</string>
- <string name="account_setup_account_type_imap_action">"IMAP-Konto"</string>
- <string name="account_setup_incoming_title">"Einstellungen für Eingangsserver"</string>
- <string name="account_setup_incoming_username_label">"Nutzername"</string>
- <string name="account_setup_incoming_password_label">"Passwort"</string>
- <string name="account_setup_incoming_pop_server_label">"POP3-Server"</string>
- <string name="account_setup_incoming_imap_server_label">"IMAP-Server"</string>
- <string name="account_setup_incoming_port_label">"Port"</string>
- <string name="account_setup_incoming_security_label">"Sicherheitstyp"</string>
- <string name="account_setup_incoming_security_none_label">"Keine"</string>
- <string name="account_setup_incoming_security_ssl_optional_label">"SSL (wenn verfügbar)"</string>
- <string name="account_setup_incoming_security_ssl_label">"SSL (immer)"</string>
- <string name="account_setup_incoming_security_tls_optional_label">"TLS (wenn verfügbar)"</string>
- <string name="account_setup_incoming_security_tls_label">"TLS (immer)"</string>
- <string name="account_setup_incoming_delete_policy_label">"E-Mail von Server löschen"</string>
- <string name="account_setup_incoming_delete_policy_never_label">"Nie"</string>
- <string name="account_setup_incoming_delete_policy_7days_label">"Nach 7 Tagen"</string>
- <string name="account_setup_incoming_delete_policy_delete_label">"Wenn ich sie aus dem Posteingang lösche"</string>
- <string name="account_setup_incoming_imap_path_prefix_label">"IMAP-Pfadpräfix"</string>
- <string name="account_setup_incoming_imap_path_prefix_hint">"Optional"</string>
- <string name="account_setup_outgoing_title">"Einstellungen für Postausgangsserver"</string>
- <string name="account_setup_outgoing_smtp_server_label">"SMTP-Server"</string>
- <string name="account_setup_outgoing_port_label">"Port"</string>
- <string name="account_setup_outgoing_security_label">"Sicherheitstyp"</string>
- <string name="account_setup_outgoing_require_login_label">"Anmeldung erforderlich"</string>
- <string name="account_setup_outgoing_username_label">"Nutzername"</string>
- <string name="account_setup_outgoing_password_label">"Passwort"</string>
- <string name="account_setup_options_title">"Kontooptionen"</string>
- <string name="account_setup_options_mail_check_frequency_label">"Abrufhäufigkeit"</string>
- <string name="account_setup_options_mail_check_frequency_never">"Nie"</string>
- <string name="account_setup_options_mail_check_frequency_5min">"Alle 5 Minuten"</string>
- <string name="account_setup_options_mail_check_frequency_10min">"Alle 10 Minuten"</string>
- <string name="account_setup_options_mail_check_frequency_15min">"Alle 15 Minuten"</string>
- <string name="account_setup_options_mail_check_frequency_30min">"Alle 30 Minuten"</string>
- <string name="account_setup_options_mail_check_frequency_1hour">"Stündlich"</string>
- <string name="account_setup_options_default_label">"E-Mails standardmäßig von diesem Konto senden"</string>
- <string name="account_setup_options_notify_label">"Benachrichtigung bei E-Mail-Eingang"</string>
- <string name="account_setup_failed_dlg_title">"Einrichtung konnte nicht abgeschlossen werden"</string>
- <string name="account_setup_failed_dlg_auth_message">"Nutzername oder Passwort falsch"</string>
- <string name="account_setup_failed_dlg_auth_message_fmt">"Nutzername oder Password falsch"\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_certificate_message">"Keine sichere Verbindung zu Server möglich"</string>
- <string name="account_setup_failed_dlg_certificate_message_fmt">"Keine sichere Verbindung zum Server möglich"\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_server_message">"Keine Verbindung zu Server möglich"</string>
- <string name="account_setup_failed_dlg_server_message_fmt">"Keine Verbindung zum Server möglich"\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_tls_required">"TLS erforderlich aber nicht von Server unterstützt"</string>
- <string name="account_setup_failed_auth_required">"Authentifizierungsmethoden nicht von Server unterstützt"</string>
- <string name="account_setup_failed_security">"Verbindung zu Server kann aufgrund eines Sicherheitsfehlers nicht geöffnet werden."</string>
- <string name="account_setup_failed_ioerror">"Verbindung zu Server kann nicht geöffnet werden"</string>
- <string name="account_setup_failed_dlg_edit_details_action">"Details bearbeiten"</string>
- <string name="account_settings_title_fmt">"Allgemeine Einstellungen"</string>
- <string name="account_settings_default_label">"Standardkonto"</string>
- <string name="account_settings_default_summary">"E-Mails standardmäßig von diesem Konto senden"</string>
- <string name="account_settings_notify_label">"E-Mail-Benachrichtigungen"</string>
- <string name="account_settings_notify_summary">"Bei E-Mail-Eingang Benachrichtigung in der Statusleiste"</string>
- <string name="account_settings_mail_check_frequency_label">"Abrufhäufigkeit"</string>
- <string name="account_settings_incoming_label">"Einstellungen für eingehende Nachrichten"</string>
- <string name="account_settings_outgoing_label">"Einstellungen für ausgehende Nachrichten"</string>
- <string name="account_settings_add_account_label">"Weiteres Konto hinzufügen"</string>
- <string name="account_settings_description_label">"Kontoname"</string>
- <string name="account_settings_name_label">"Ihr Name"</string>
- <string name="account_settings_notifications">"Benachrichtigungseinstellungen"</string>
- <string name="account_settings_vibrate_enable">"Vibration"</string>
- <string name="account_settings_vibrate_summary">"Bei E-Mail-Eingang zusätzlich vibrieren"</string>
- <string name="account_settings_ringtone">"Klingelton auswählen"</string>
- <string name="account_settings_servers">"Servereinstellungen"</string>
- <string name="account_delete_dlg_title">"Konto entfernen"</string>
- <string name="account_delete_dlg_instructions_fmt">"Das Konto \"<xliff:g id="ACCOUNT">%s</xliff:g>\" wird aus Email entfernt."</string>
- <string name="provider_note_yahoo">"Der Zugang zum Postfach bestimmter E-Mail-Konten von Yahoo! wird nicht unterstützt. Bei Verbindungsproblemen besuchen Sie die Website von Yahoo! für weitere Informationen."</string>
- <string name="provider_note_yahoo_uk">"Vor Eröffnung dieses E-Mail-Kontos bitte die Website von Yahoo! besuchen und E-Mail-Zugang über POP3 für dieses Konto aktivieren."</string>
- <string name="provider_note_live">"Nur einige \"Plus\"-Konten ermöglichen einen POP-Zugang und damit diesem Programm, eine Verbindung aufzubauen. Sollten Sie nicht dazu in der Lage sein, sich mit Ihrer korrekten E-Mail-Adresse und dem richtigen Password anzumelden, verfügen Sie möglicherweise nicht über ein kostenpflichtiges \"Plus\"-Konto. Starten Sie Ihren Webbrowser, um Zugriff auf diese Konten zu erlangen."</string>
- <string name="provider_note_t_online">"Vor Erstellung des E-Mail Kontos bitte \\\"eMail-Passwort\\\" für den POP3-Zugang auf der T-Online Homepage einrichten."</string>
-</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
deleted file mode 100644
index d9c240b1e..000000000
--- a/res/values-es/strings.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="read_attachment_label">"leer los archivos adjuntos del mensaje"</string>
- <string name="read_attachment_desc">"Permite que esta aplicación lea los archivos adjuntos del correo electrónico."</string>
- <string name="app_name">"Correo electrónico"</string>
- <string name="accounts_title">"Tus cuentas"</string>
- <string name="compose_title">"Redactar"</string>
- <string name="debug_title">"Depurar"</string>
- <string name="next_action">"Siguiente"</string>
- <string name="okay_action">"Aceptar"</string>
- <string name="cancel_action">"Cancelar"</string>
- <string name="send_action">"Enviar"</string>
- <string name="reply_action">"Responder"</string>
- <string name="reply_all_action">"Responder a todos"</string>
- <string name="delete_action">"Suprimir"</string>
- <string name="forward_action">"Reenviar"</string>
- <string name="done_action">"Finalizado"</string>
- <string name="discard_action">"Descartar"</string>
- <string name="save_draft_action">"Guardar como borrador"</string>
- <string name="refresh_action">"Actualizar"</string>
- <string name="add_account_action">"Añadir cuenta"</string>
- <string name="compose_action">"Redactar"</string>
- <string name="search_action">"Buscar"</string>
- <string name="open_action">"Abrir"</string>
- <string name="account_settings_action">"Configuración"</string>
- <string name="remove_account_action">"Eliminar cuenta"</string>
- <string name="accounts_action">"Cuentas"</string>
- <string name="mark_as_read_action">"Marcar como leída"</string>
- <string name="mark_as_unread_action">"Marcar como no leído"</string>
- <string name="add_cc_bcc_action">"Añadir Cc/CCO"</string>
- <string name="add_attachment_action">"Añadir archivo adjunto"</string>
- <string name="dump_settings_action">"Configuración de volcado"</string>
- <string name="accounts_context_menu_title">"Opciones de cuenta"</string>
- <string name="status_loading_more">"Cargando mensajes..."</string>
- <string name="status_network_error">"Error de conexión"</string>
- <string name="status_loading_more_failed">"Intentar cargar más mensajes"</string>
- <string name="notification_new_title">"Nuevo mensaje"</string>
- <string name="notification_new_one_account_fmt">"<xliff:g id="UNREAD_MESSAGE_COUNT">%d</xliff:g> no leídos (<xliff:g id="ACCOUNT">%s</xliff:g>)"</string>
- <string name="notification_new_multi_account_fmt">"en <xliff:g id="NUMBER_ACCOUNTS">%d</xliff:g> cuentas"</string>
- <string name="special_mailbox_name_inbox">"Recibidos"</string>
- <string name="accounts_welcome">"Te damos la bienvenida a la configuración del correo electrónico."\n\n"Usa cualquier cuenta de correo electrónico con \"Correo electrónico\"."\n\n"Las cuentas de correo electrónico más populares se pueden configurar en 2 pasos."</string>
- <string name="debug_version_fmt">"Versión: <xliff:g id="VERSION">%s</xliff:g>"</string>
- <string name="debug_enable_debug_logging_label">"¿Deseas habilitar un registro adicional de depuración?"</string>
- <string name="debug_enable_sensitive_logging_label">"¿Deseas habilitar el registro de depuración de la información confidencial? (Es posible que se muestren las contraseñas en los registros)."</string>
- <string name="message_list_load_more_messages_action">"Cargar más mensajes"</string>
- <string name="message_compose_to_hint">"Para"</string>
- <string name="message_compose_cc_hint">"Cc"</string>
- <string name="message_compose_bcc_hint">"CCO"</string>
- <string name="message_compose_subject_hint">"Asunto"</string>
- <string name="message_compose_fwd_header_fmt">\n\n"-------- Original Message --------"\n"Subject: <xliff:g id="SUBJECT">%s</xliff:g>"\n"From: <xliff:g id="SENDER">%s</xliff:g>"\n"To: <xliff:g id="TO">%s</xliff:g>"\n"CC: <xliff:g id="CC_0">%s</xliff:g>"\n\n</string>
- <string name="message_compose_reply_header_fmt">\n\n"<xliff:g id="SENDER">%s</xliff:g> wrote:"\n\n</string>
- <string name="message_compose_quoted_text_label">"Texto entre comillas"</string>
- <string name="message_compose_error_no_recipients">"Debes especificar, al menos, un destinatario."</string>
- <string name="message_compose_attachments_skipped_toast">"No se pueden reenviar algunos archivos adjuntos porque no se han descargado."</string>
- <string name="message_view_to_label">"Para:"</string>
- <string name="message_view_cc_label">"Cc:"</string>
- <string name="message_view_attachment_view_action">"Abrir"</string>
- <string name="message_view_attachment_download_action">"Guardar"</string>
- <string name="message_view_prev_action">"Mensaje anterior"</string>
- <string name="message_view_next_action">"Siguiente mensaje"</string>
- <string name="message_view_status_attachment_saved">"El archivo adjunto se ha guardado en una tarjeta SD como <xliff:g id="FILENAME">%s</xliff:g>."</string>
- <string name="message_view_status_attachment_not_saved">"No es posible guardar el archivo adjunto en la tarjeta SD."</string>
- <string name="message_view_show_pictures_instructions">"Selecciona \"Mostrar imágenes\" para visualizar las imágenes incrustadas."</string>
- <string name="message_view_show_pictures_action">"Mostrar imágenes"</string>
- <string name="message_view_fetching_attachment_toast">"Obteniendo archivo adjunto"</string>
- <string name="message_deleted_toast">"Mensaje suprimido"</string>
- <string name="message_discarded_toast">"Mensaje descartado"</string>
- <string name="message_saved_toast">"Mensaje guardado como borrador"</string>
- <string name="account_setup_basics_title">"Configurar correo electrónico"</string>
- <string name="account_setup_basics_instructions">"Introduce la dirección de correo electrónico de tu cuenta:"</string>
- <string name="account_setup_basics_email_hint">"Dirección de correo electrónico"</string>
- <string name="account_setup_basics_password_hint">"Contraseña"</string>
- <string name="account_setup_basics_default_label">"Enviar correo electrónico desde esta cuenta de forma predeterminada"</string>
- <string name="account_setup_basics_manual_setup_action">"Configuración manual"</string>
- <string name="account_setup_username_password_toast">"Introduce una dirección de correo electrónico y una contraseña válidas."</string>
- <string name="account_setup_check_settings_retr_info_msg">"Recuperando la información de la cuenta..."</string>
- <string name="account_setup_check_settings_check_incoming_msg">"Comprobando la configuración del servidor de entrada..."</string>
- <string name="account_setup_check_settings_check_outgoing_msg">"Comprobando la configuración del servidor de salida..."</string>
- <string name="account_setup_check_settings_canceling_msg">"Cancelando..."</string>
- <string name="account_setup_names_title">"Configurar correo electrónico"</string>
- <string name="account_setup_names_instructions">"Tu cuenta ya está configurada y el correo electrónico está por llegar."</string>
- <string name="account_setup_names_account_name_label">"Asignar un nombre a esta cuenta (opcional)"</string>
- <string name="account_setup_names_user_name_label">"Tu nombre (aparece en los mensajes salientes)"</string>
- <string name="account_setup_account_type_title">"Añadir una cuenta de correo electrónico nueva"</string>
- <string name="account_setup_account_type_instructions">"¿Qué tipo de cuenta es ésta?"</string>
- <string name="account_setup_account_type_pop_action">"Cuenta POP3"</string>
- <string name="account_setup_account_type_imap_action">"Cuenta IMAP"</string>
- <string name="account_setup_incoming_title">"Configuración del servidor de entrada"</string>
- <string name="account_setup_incoming_username_label">"Nombre de usuario"</string>
- <string name="account_setup_incoming_password_label">"Contraseña"</string>
- <string name="account_setup_incoming_pop_server_label">"Servidor POP3"</string>
- <string name="account_setup_incoming_imap_server_label">"Servidor IMAP"</string>
- <string name="account_setup_incoming_port_label">"Puerto"</string>
- <string name="account_setup_incoming_security_label">"Tipo de seguridad"</string>
- <string name="account_setup_incoming_security_none_label">"Ninguna"</string>
- <string name="account_setup_incoming_security_ssl_optional_label">"SSL (si está disponible)"</string>
- <string name="account_setup_incoming_security_ssl_label">"SSL (siempre)"</string>
- <string name="account_setup_incoming_security_tls_optional_label">"TLS (si está disponible)"</string>
- <string name="account_setup_incoming_security_tls_label">"TLS (siempre)"</string>
- <string name="account_setup_incoming_delete_policy_label">"Suprimir correo electrónico del servidor"</string>
- <string name="account_setup_incoming_delete_policy_never_label">"Nunca"</string>
- <string name="account_setup_incoming_delete_policy_7days_label">"Después de 7 días"</string>
- <string name="account_setup_incoming_delete_policy_delete_label">"Cuando suprimo algún mensaje de \"Recibidos\""</string>
- <string name="account_setup_incoming_imap_path_prefix_label">"Prefijo de ruta IMAP"</string>
- <string name="account_setup_incoming_imap_path_prefix_hint">"Opcional"</string>
- <string name="account_setup_outgoing_title">"Configuración del servidor de salida"</string>
- <string name="account_setup_outgoing_smtp_server_label">"Servidor SMTP"</string>
- <string name="account_setup_outgoing_port_label">"Puerto"</string>
- <string name="account_setup_outgoing_security_label">"Tipo de seguridad"</string>
- <string name="account_setup_outgoing_require_login_label">"Acceso obligatorio"</string>
- <string name="account_setup_outgoing_username_label">"Nombre de usuario"</string>
- <string name="account_setup_outgoing_password_label">"Contraseña"</string>
- <string name="account_setup_options_title">"Opciones de cuenta"</string>
- <string name="account_setup_options_mail_check_frequency_label">"Frecuencia de comprobación del correo electrónico"</string>
- <string name="account_setup_options_mail_check_frequency_never">"Nunca"</string>
- <string name="account_setup_options_mail_check_frequency_5min">"Cada 5 minutos"</string>
- <string name="account_setup_options_mail_check_frequency_10min">"Cada 10 minutos"</string>
- <string name="account_setup_options_mail_check_frequency_15min">"Cada 15 minutos"</string>
- <string name="account_setup_options_mail_check_frequency_30min">"Cada 30 minutos"</string>
- <string name="account_setup_options_mail_check_frequency_1hour">"Cada hora"</string>
- <string name="account_setup_options_default_label">"Enviar correo electrónico desde esta cuenta de forma predeterminada"</string>
- <string name="account_setup_options_notify_label">"Avisarme cuando llegue un correo electrónico"</string>
- <string name="account_setup_failed_dlg_title">"No se ha podido completar la configuración."</string>
- <string name="account_setup_failed_dlg_auth_message">"Nombre de usuario o contraseña incorrecta"</string>
- <string name="account_setup_failed_dlg_auth_message_fmt">"Nombre de usuario o contraseña incorrecta"\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_certificate_message">"No se puede establecer conexión de forma segura con el servidor."</string>
- <string name="account_setup_failed_dlg_certificate_message_fmt">"No se puede establecer una conexión de forma segura con el servidor."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_server_message">"No se puede establecer conexión con el servidor."</string>
- <string name="account_setup_failed_dlg_server_message_fmt">"No se puede establecer una conexión con el servidor."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_tls_required">"El protocolo TLS es obligatorio, pero el servidor no lo admite."</string>
- <string name="account_setup_failed_auth_required">"El servidor no admite los métodos de autenticación."</string>
- <string name="account_setup_failed_security">"No se puede abrir la conexión con el servidor debido a un error de seguridad."</string>
- <string name="account_setup_failed_ioerror">"No se puede abrir la conexión con el servidor."</string>
- <string name="account_setup_failed_dlg_edit_details_action">"Editar detalles"</string>
- <string name="account_settings_title_fmt">"Configuración general"</string>
- <string name="account_settings_default_label">"Cuenta predeterminada"</string>
- <string name="account_settings_default_summary">"Enviar correo electrónico desde esta cuenta de forma predeterminada"</string>
- <string name="account_settings_notify_label">"Notificaciones de correo electrónico"</string>
- <string name="account_settings_notify_summary">"Notificar en la barra de estado cuando llegue un mensaje"</string>
- <string name="account_settings_mail_check_frequency_label">"Frecuencia de comprobación del correo"</string>
- <string name="account_settings_incoming_label">"Configuración entrante"</string>
- <string name="account_settings_outgoing_label">"Configuración saliente"</string>
- <string name="account_settings_add_account_label">"Añadir otra cuenta"</string>
- <string name="account_settings_description_label">"Nombre de cuenta"</string>
- <string name="account_settings_name_label">"Tu nombre"</string>
- <string name="account_settings_notifications">"Configuración de la notificación"</string>
- <string name="account_settings_vibrate_enable">"Vibrar"</string>
- <string name="account_settings_vibrate_summary">"Vibrar también cuando llegue un mensaje"</string>
- <string name="account_settings_ringtone">"Seleccionar tono de llamada"</string>
- <string name="account_settings_servers">"Configuración del servidor"</string>
- <string name="account_delete_dlg_title">"Eliminar cuenta"</string>
- <string name="account_delete_dlg_instructions_fmt">"Se va a eliminar la cuenta \"<xliff:g id="ACCOUNT">%s</xliff:g>\" de \"Correo electrónico\"."</string>
- <string name="provider_note_yahoo">"Algunos tipos de cuentas de correo de Yahoo! no permiten acceder al buzón de correo. Si tienes problemas de conexión, visita yahoo.com para obtener información adicional al respecto."</string>
- <string name="provider_note_yahoo_uk">"Antes de configurar esta cuenta de correo electrónico, visita el sitio web de Yahoo! y habilita el acceso al correo electrónico POP3 para esta cuenta."</string>
- <string name="provider_note_live">"Sólo algunas cuentas \"Plus\" incluyen el acceso POP, que permite que este programa se conecte. Si no puedes acceder con la dirección de correo electrónico y la contraseña adecuadas, es posible que no dispongas de una cuenta \"Plus\" de pago. Usa el navegador web para acceder a estas cuentas de correo."</string>
- <string name="provider_note_t_online">"Antes de configurar esta cuenta de correo electrónico, visita el sitio web de T-Online y crea una contraseña para el acceso al correo electrónico POP3."</string>
-</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
deleted file mode 100644
index af017d82e..000000000
--- a/res/values-fr/strings.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="read_attachment_label">"lire les pièces jointes"</string>
- <string name="read_attachment_desc">"Permet à cette application de lire les pièces jointes aux e-mails."</string>
- <string name="app_name">"E-mail"</string>
- <string name="accounts_title">"Vos comptes"</string>
- <string name="compose_title">"Nouveau message"</string>
- <string name="debug_title">"Déboguer"</string>
- <string name="next_action">"Suivant"</string>
- <string name="okay_action">"OK"</string>
- <string name="cancel_action">"Annuler"</string>
- <string name="send_action">"Envoyer"</string>
- <string name="reply_action">"Répondre"</string>
- <string name="reply_all_action">"Répondre à tous"</string>
- <string name="delete_action">"Supprimer"</string>
- <string name="forward_action">"Transférer"</string>
- <string name="done_action">"OK"</string>
- <string name="discard_action">"Supprimer"</string>
- <string name="save_draft_action">"Enregistrer en tant que brouillon"</string>
- <string name="refresh_action">"Actualiser"</string>
- <string name="add_account_action">"Ajouter un compte"</string>
- <string name="compose_action">"Nouveau message"</string>
- <string name="search_action">"Rechercher"</string>
- <string name="open_action">"Ouvrir"</string>
- <string name="account_settings_action">"Paramètres du compte"</string>
- <string name="remove_account_action">"Supprimer le compte"</string>
- <string name="accounts_action">"Comptes"</string>
- <string name="mark_as_read_action">"Marquer comme lu"</string>
- <string name="mark_as_unread_action">"Marquer comme non lu"</string>
- <string name="add_cc_bcc_action">"Ajouter les champs Cc/Cci"</string>
- <string name="add_attachment_action">"Ajouter une pièce jointe"</string>
- <string name="dump_settings_action">"Paramètres d\'image mémoire"</string>
- <string name="accounts_context_menu_title">"Options de compte"</string>
- <string name="status_loading_more">"Chargement des messages en cours..."</string>
- <string name="status_network_error">"Erreur de connexion"</string>
- <string name="status_loading_more_failed">"Essayer de charger plus de messages"</string>
- <string name="notification_new_title">"Nouvel e-mail"</string>
- <string name="notification_new_one_account_fmt">"<xliff:g id="UNREAD_MESSAGE_COUNT">%d</xliff:g> non lus (<xliff:g id="ACCOUNT">%s</xliff:g>)"</string>
- <string name="notification_new_multi_account_fmt">"dans <xliff:g id="NUMBER_ACCOUNTS">%d</xliff:g> comptes"</string>
- <string name="special_mailbox_name_inbox">"Boîte de réception"</string>
- <string name="accounts_welcome">"Bienvenue dans le programme de configuration de votre messagerie électronique !"\n\n"Utilisez le compte de votre choix."\n\n"Les comptes de messagerie les plus courants peuvent être configurés en deux étapes !"</string>
- <string name="debug_version_fmt">"Version : <xliff:g id="VERSION">%s</xliff:g>"</string>
- <string name="debug_enable_debug_logging_label">"Activer la consignation supplémentaire des données de débogage ?"</string>
- <string name="debug_enable_sensitive_logging_label">"Activer la consignation des données de débogage pour les informations sensibles ? (Les mots de passe pourront s\'afficher dans les journaux.)"</string>
- <string name="message_list_load_more_messages_action">"Charger plus de messages"</string>
- <string name="message_compose_to_hint">"À"</string>
- <string name="message_compose_cc_hint">"Cc"</string>
- <string name="message_compose_bcc_hint">"Cci"</string>
- <string name="message_compose_subject_hint">"Objet"</string>
- <string name="message_compose_fwd_header_fmt">\n\n"-------- Message original --------"\n"Objet : <xliff:g id="SUBJECT">%s</xliff:g>"\n"De : <xliff:g id="SENDER">%s</xliff:g>"\n"À : <xliff:g id="TO">%s</xliff:g>"\n"Cc : <xliff:g id="CC_0">%s</xliff:g>"\n\n</string>
- <string name="message_compose_reply_header_fmt">\n\n"<xliff:g id="SENDER">%s</xliff:g> a écrit :"\n\n</string>
- <string name="message_compose_quoted_text_label">"Texte du message précédent"</string>
- <string name="message_compose_error_no_recipients">"Vous devez ajouter au moins un destinataire."</string>
- <string name="message_compose_attachments_skipped_toast">"Impossible de transférer certaines pièces jointes : elles n\'ont pas été téléchargées."</string>
- <string name="message_view_to_label">"À :"</string>
- <string name="message_view_cc_label">"Cc :"</string>
- <string name="message_view_attachment_view_action">"Ouvrir"</string>
- <string name="message_view_attachment_download_action">"Enregistrer"</string>
- <string name="message_view_prev_action">"Message préc."</string>
- <string name="message_view_next_action">"Message suivant"</string>
- <string name="message_view_status_attachment_saved">"Pièce jointe enregistrée sur la carte SD sous le nom <xliff:g id="FILENAME">%s</xliff:g>."</string>
- <string name="message_view_status_attachment_not_saved">"Impossible d\'enregistrer la pièce jointe sur la carte SD."</string>
- <string name="message_view_show_pictures_instructions">"Sélectionnez \"Afficher les images\" pour afficher les images intégrées."</string>
- <string name="message_view_show_pictures_action">"Afficher les images"</string>
- <string name="message_view_fetching_attachment_toast">"Récupération de la pièce jointe."</string>
- <string name="message_deleted_toast">"Message supprimé."</string>
- <string name="message_discarded_toast">"Message supprimé."</string>
- <string name="message_saved_toast">"Message enregistré en tant que brouillon."</string>
- <string name="account_setup_basics_title">"Configurer la messagerie électronique"</string>
- <string name="account_setup_basics_instructions">"Saisissez l\'adresse e-mail de votre compte :"</string>
- <string name="account_setup_basics_email_hint">"Adresse e-mail"</string>
- <string name="account_setup_basics_password_hint">"Mot de passe"</string>
- <string name="account_setup_basics_default_label">"Par défaut, envoyer les e-mails avec ce compte"</string>
- <string name="account_setup_basics_manual_setup_action">"Configuration manuelle"</string>
- <string name="account_setup_username_password_toast">"Veuillez saisir une adresse e-mail et un mot de passe corrects."</string>
- <string name="account_setup_check_settings_retr_info_msg">"Récupération des informations sur le compte…"</string>
- <string name="account_setup_check_settings_check_incoming_msg">"Vérification des paramètres de serveur entrant…"</string>
- <string name="account_setup_check_settings_check_outgoing_msg">"Vérification des paramètres de serveur sortant…"</string>
- <string name="account_setup_check_settings_canceling_msg">"Annulation en cours..."</string>
- <string name="account_setup_names_title">"Configurer la messagerie électronique"</string>
- <string name="account_setup_names_instructions">"Votre compte est configuré et votre messagerie est active !"</string>
- <string name="account_setup_names_account_name_label">"Donner un nom à ce compte (facultatif)"</string>
- <string name="account_setup_names_user_name_label">"Votre nom (affiché sur les messages sortants)"</string>
- <string name="account_setup_account_type_title">"Ajouter un compte de messagerie"</string>
- <string name="account_setup_account_type_instructions">"De quel type de compte s\'agit-il ?"</string>
- <string name="account_setup_account_type_pop_action">"Compte POP3"</string>
- <string name="account_setup_account_type_imap_action">"Compte IMAP"</string>
- <string name="account_setup_incoming_title">"Paramètres de serveur entrant"</string>
- <string name="account_setup_incoming_username_label">"Nom d\'utilisateur"</string>
- <string name="account_setup_incoming_password_label">"Mot de passe"</string>
- <string name="account_setup_incoming_pop_server_label">"Serveur POP3"</string>
- <string name="account_setup_incoming_imap_server_label">"Serveur IMAP"</string>
- <string name="account_setup_incoming_port_label">"Port"</string>
- <string name="account_setup_incoming_security_label">"Type de sécurité"</string>
- <string name="account_setup_incoming_security_none_label">"Aucun protocole"</string>
- <string name="account_setup_incoming_security_ssl_optional_label">"SSL (si disponible)"</string>
- <string name="account_setup_incoming_security_ssl_label">"SSL (toujours)"</string>
- <string name="account_setup_incoming_security_tls_optional_label">"TLS (si disponible)"</string>
- <string name="account_setup_incoming_security_tls_label">"TLS (toujours)"</string>
- <string name="account_setup_incoming_delete_policy_label">"Supprimer les e-mails du serveur"</string>
- <string name="account_setup_incoming_delete_policy_never_label">"Jamais"</string>
- <string name="account_setup_incoming_delete_policy_7days_label">"Au bout de 7 jours"</string>
- <string name="account_setup_incoming_delete_policy_delete_label">"Si messages suppr. de boîte de récep."</string>
- <string name="account_setup_incoming_imap_path_prefix_label">"Préfixe du chemin IMAP"</string>
- <string name="account_setup_incoming_imap_path_prefix_hint">"Facultatif"</string>
- <string name="account_setup_outgoing_title">"Paramètres de serveur sortant"</string>
- <string name="account_setup_outgoing_smtp_server_label">"Serveur SMTP"</string>
- <string name="account_setup_outgoing_port_label">"Port"</string>
- <string name="account_setup_outgoing_security_label">"Type de sécurité"</string>
- <string name="account_setup_outgoing_require_login_label">"Connexion obligatoire."</string>
- <string name="account_setup_outgoing_username_label">"Nom d\'utilisateur"</string>
- <string name="account_setup_outgoing_password_label">"Mot de passe"</string>
- <string name="account_setup_options_title">"Options de compte"</string>
- <string name="account_setup_options_mail_check_frequency_label">"Vérification des e-mails"</string>
- <string name="account_setup_options_mail_check_frequency_never">"Jamais"</string>
- <string name="account_setup_options_mail_check_frequency_5min">"Toutes les 5 minutes"</string>
- <string name="account_setup_options_mail_check_frequency_10min">"Toutes les 10 minutes"</string>
- <string name="account_setup_options_mail_check_frequency_15min">"Toutes les 15 minutes"</string>
- <string name="account_setup_options_mail_check_frequency_30min">"Toutes les 30 minutes"</string>
- <string name="account_setup_options_mail_check_frequency_1hour">"Toutes les heures"</string>
- <string name="account_setup_options_default_label">"Par défaut, envoyer les e-mails avec ce compte"</string>
- <string name="account_setup_options_notify_label">"Afficher une notification lors de la réception d\'un e-mail"</string>
- <string name="account_setup_failed_dlg_title">"La configuration a échoué."</string>
- <string name="account_setup_failed_dlg_auth_message">"Nom d\'utilisateur ou mot de passe incorrect."</string>
- <string name="account_setup_failed_dlg_auth_message_fmt">"Nom d\'utilisateur ou mot de passe incorrect."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_certificate_message">"Impossible d\'établir une connexion sécurisée avec le serveur."</string>
- <string name="account_setup_failed_dlg_certificate_message_fmt">"Impossible d\'établir une connexion sécurisée avec le serveur."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_server_message">"Impossible d\'établir une connexion avec le serveur."</string>
- <string name="account_setup_failed_dlg_server_message_fmt">"Impossible d\'établir une connexion avec le serveur."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_tls_required">"Protocole TLS requis mais non pris en charge par le serveur."</string>
- <string name="account_setup_failed_auth_required">"Les méthodes d\'authentification ne sont pas prises en charge par le serveur."</string>
- <string name="account_setup_failed_security">"Impossible d\'établir une connexion avec le serveur en raison d\'une erreur de sécurité."</string>
- <string name="account_setup_failed_ioerror">"Impossible d\'établir une connexion avec le serveur."</string>
- <string name="account_setup_failed_dlg_edit_details_action">"Modifier les infos"</string>
- <string name="account_settings_title_fmt">"Paramètres généraux"</string>
- <string name="account_settings_default_label">"Compte par défaut"</string>
- <string name="account_settings_default_summary">"Par défaut, envoyer les e-mails avec ce compte"</string>
- <string name="account_settings_notify_label">"Notifications d\'e-mails"</string>
- <string name="account_settings_notify_summary">"Afficher une notification dans la barre d\'état lors de la réception d\'un e-mail"</string>
- <string name="account_settings_mail_check_frequency_label">"Fréquence de vérification des e-mails"</string>
- <string name="account_settings_incoming_label">"Paramètres de réception"</string>
- <string name="account_settings_outgoing_label">"Paramètres d\'envoi"</string>
- <string name="account_settings_add_account_label">"Ajouter un autre compte"</string>
- <string name="account_settings_description_label">"Nom du compte"</string>
- <string name="account_settings_name_label">"Votre nom"</string>
- <string name="account_settings_notifications">"Paramètres de notification"</string>
- <string name="account_settings_vibrate_enable">"Vibrer"</string>
- <string name="account_settings_vibrate_summary">"Vibrer également lors de la réception d\'un e-mail"</string>
- <string name="account_settings_ringtone">"Sélectionner la sonnerie"</string>
- <string name="account_settings_servers">"Paramètres du serveur"</string>
- <string name="account_delete_dlg_title">"Supprimer le compte"</string>
- <string name="account_delete_dlg_instructions_fmt">"Le compte \"<xliff:g id="ACCOUNT">%s</xliff:g>\" va être supprimé de votre messagerie."</string>
- <string name="provider_note_yahoo">"L\'accès à la boîte aux lettres n\'est pas possible avec certains types de comptes Yahoo!. En cas de problème de connexion, consultez le site yahoo.fr pour obtenir plus d\'informations."</string>
- <string name="provider_note_yahoo_uk">"Avant de configurer ce compte de messagerie, veuillez consulter le site de Yahoo! et activer l\'accès POP3 pour ce compte."</string>
- <string name="provider_note_live">"Seuls certains comptes \"Plus\" comportent un accès POP permettant à ce programme de se connecter. Si vous ne parvenez pas à vous connecter avec l\'adresse e-mail et le mot de passe corrects, vous ne disposez peut-être pas d\'un compte payant \"Plus\". Pour accéder à ces comptes de messagerie, lancez votre navigateur Web."</string>
- <string name="provider_note_t_online">"Avant de configurer ce compte de messagerie, veuillez consulter le site de T-Online et créer un mot de passe de messagerie POP3."</string>
-</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
deleted file mode 100644
index 53ca6f7fe..000000000
--- a/res/values-it/strings.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="read_attachment_label">"lettura allegati email"</string>
- <string name="read_attachment_desc">"Consente all\'applicazione di leggere i tuoi allegati email."</string>
- <string name="app_name">"Email"</string>
- <string name="accounts_title">"I tuoi account"</string>
- <string name="compose_title">"Scrivi"</string>
- <string name="debug_title">"Debug"</string>
- <string name="next_action">"Avanti"</string>
- <string name="okay_action">"OK"</string>
- <string name="cancel_action">"Annulla"</string>
- <string name="send_action">"Invia"</string>
- <string name="reply_action">"Rispondi"</string>
- <string name="reply_all_action">"Rispondi a tutti"</string>
- <string name="delete_action">"Elimina"</string>
- <string name="forward_action">"Inoltra"</string>
- <string name="done_action">"Completato"</string>
- <string name="discard_action">"Elimina"</string>
- <string name="save_draft_action">"Salva come bozza"</string>
- <string name="refresh_action">"Aggiorna"</string>
- <string name="add_account_action">"Aggiungi account"</string>
- <string name="compose_action">"Scrivi"</string>
- <string name="search_action">"Cerca"</string>
- <string name="open_action">"Apri"</string>
- <string name="account_settings_action">"Impostazioni account"</string>
- <string name="remove_account_action">"Rimuovi account"</string>
- <string name="accounts_action">"Account"</string>
- <string name="mark_as_read_action">"Segna come Già letto"</string>
- <string name="mark_as_unread_action">"Segna come da leggere"</string>
- <string name="add_cc_bcc_action">"Aggiungi Cc/Ccn"</string>
- <string name="add_attachment_action">"Aggiungi allegato"</string>
- <string name="dump_settings_action">"Scarica impostazioni"</string>
- <string name="accounts_context_menu_title">"Opzioni account"</string>
- <string name="status_loading_more">"Caricamento messaggi in corso..."</string>
- <string name="status_network_error">"Errore di connessione"</string>
- <string name="status_loading_more_failed">"Prova nuovamente a caricare altri messaggi"</string>
- <string name="notification_new_title">"Nuova email"</string>
- <string name="notification_new_one_account_fmt">"<xliff:g id="UNREAD_MESSAGE_COUNT">%d</xliff:g> da leggere (<xliff:g id="ACCOUNT">%s</xliff:g>)"</string>
- <string name="notification_new_multi_account_fmt">"in <xliff:g id="NUMBER_ACCOUNTS">%d</xliff:g> account"</string>
- <string name="special_mailbox_name_inbox">"Posta in arrivo"</string>
- <string name="accounts_welcome">"Benvenuto in Impostazione email."\n\n"Usa qualunque account email con Email."\n\n"Puoi impostare gli account email più popolari in due semplici passaggi."</string>
- <string name="debug_version_fmt">"Versione: <xliff:g id="VERSION">%s</xliff:g>"</string>
- <string name="debug_enable_debug_logging_label">"Attivare la registrazione debug aggiuntiva?"</string>
- <string name="debug_enable_sensitive_logging_label">"Attivare la registrazione debug delle informazioni riservate? (Nei registri potrebbero essere visualizzate le password.)"</string>
- <string name="message_list_load_more_messages_action">"Carica ulteriori messaggi"</string>
- <string name="message_compose_to_hint">"A"</string>
- <string name="message_compose_cc_hint">"Cc"</string>
- <string name="message_compose_bcc_hint">"Ccn"</string>
- <string name="message_compose_subject_hint">"Oggetto"</string>
- <string name="message_compose_fwd_header_fmt">\n\n"-------- Messaggio originale --------"\n"Oggetto: <xliff:g id="SUBJECT">%s</xliff:g>"\n"Da: <xliff:g id="SENDER">%s</xliff:g>"\n"A: <xliff:g id="TO">%s</xliff:g>"\n"CC: <xliff:g id="CC_0">%s</xliff:g>"\n\n</string>
- <string name="message_compose_reply_header_fmt">\n\n"<xliff:g id="SENDER">%s</xliff:g> ha scritto:"\n\n</string>
- <string name="message_compose_quoted_text_label">"Testo tra virgolette"</string>
- <string name="message_compose_error_no_recipients">"Devi aggiungere almeno un destinatario."</string>
- <string name="message_compose_attachments_skipped_toast">"Impossibile inviare alcuni allegati poiché non sono stati scaricati."</string>
- <string name="message_view_to_label">"A:"</string>
- <string name="message_view_cc_label">"Cc:"</string>
- <string name="message_view_attachment_view_action">"Apri"</string>
- <string name="message_view_attachment_download_action">"Salva"</string>
- <string name="message_view_prev_action">"Messaggio precedente"</string>
- <string name="message_view_next_action">"Messaggio successivo"</string>
- <string name="message_view_status_attachment_saved">"Allegato salvato su scheda SD come <xliff:g id="FILENAME">%s</xliff:g>."</string>
- <string name="message_view_status_attachment_not_saved">"Impossibile salvare l\'allegato nella scheda SD."</string>
- <string name="message_view_show_pictures_instructions">"Seleziona \"Mostra immagini\" per visualizzare le immagini incorporate."</string>
- <string name="message_view_show_pictures_action">"Mostra immagini"</string>
- <string name="message_view_fetching_attachment_toast">"Recupero allegato in corso."</string>
- <string name="message_deleted_toast">"Messaggio eliminato."</string>
- <string name="message_discarded_toast">"Messaggio eliminato."</string>
- <string name="message_saved_toast">"Messaggio salvato come bozza."</string>
- <string name="account_setup_basics_title">"Imposta email"</string>
- <string name="account_setup_basics_instructions">"Digita l\'indirizzo email del tuo account:"</string>
- <string name="account_setup_basics_email_hint">"Indirizzo email"</string>
- <string name="account_setup_basics_password_hint">"Password"</string>
- <string name="account_setup_basics_default_label">"Invia email da questo account per impostazione predefinita."</string>
- <string name="account_setup_basics_manual_setup_action">"Impostazione manuale"</string>
- <string name="account_setup_username_password_toast">"Digita un indirizzo email e una password validi."</string>
- <string name="account_setup_check_settings_retr_info_msg">"Recupero informazioni sull\'account in corso…"</string>
- <string name="account_setup_check_settings_check_incoming_msg">"Verifica delle impostazioni del server della posta in arrivo in corso…"</string>
- <string name="account_setup_check_settings_check_outgoing_msg">"Verifica delle impostazioni del server della posta in uscita in corso…"</string>
- <string name="account_setup_check_settings_canceling_msg">"Annullamento in corso..."</string>
- <string name="account_setup_names_title">"Imposta email"</string>
- <string name="account_setup_names_instructions">"Il tuo account è stato impostato e l\'email sarà presto disponibile."</string>
- <string name="account_setup_names_account_name_label">"Assegna un nome all\'account (facoltativo)"</string>
- <string name="account_setup_names_user_name_label">"Il tuo nome (visualizzato nei messaggi in uscita)"</string>
- <string name="account_setup_account_type_title">"Aggiungi un nuovo account email"</string>
- <string name="account_setup_account_type_instructions">"Di quale tipo di account si tratta?"</string>
- <string name="account_setup_account_type_pop_action">"Account POP3"</string>
- <string name="account_setup_account_type_imap_action">"Account IMAP"</string>
- <string name="account_setup_incoming_title">"Impostazioni server della Posta in arrivo"</string>
- <string name="account_setup_incoming_username_label">"Nome utente"</string>
- <string name="account_setup_incoming_password_label">"Password"</string>
- <string name="account_setup_incoming_pop_server_label">"Server POP3"</string>
- <string name="account_setup_incoming_imap_server_label">"Server IMAP"</string>
- <string name="account_setup_incoming_port_label">"Porta"</string>
- <string name="account_setup_incoming_security_label">"Tipo di protezione"</string>
- <string name="account_setup_incoming_security_none_label">"Nessuno"</string>
- <string name="account_setup_incoming_security_ssl_optional_label">"SSL (se disponibile)"</string>
- <string name="account_setup_incoming_security_ssl_label">"SSL (sempre)"</string>
- <string name="account_setup_incoming_security_tls_optional_label">"TLS (se disponibile)"</string>
- <string name="account_setup_incoming_security_tls_label">"TLS (sempre)"</string>
- <string name="account_setup_incoming_delete_policy_label">"Elimina email da server"</string>
- <string name="account_setup_incoming_delete_policy_never_label">"Mai"</string>
- <string name="account_setup_incoming_delete_policy_7days_label">"Dopo 7 giorni"</string>
- <string name="account_setup_incoming_delete_policy_delete_label">"Quando elimino dalla Posta in arrivo"</string>
- <string name="account_setup_incoming_imap_path_prefix_label">"Prefisso percorso IMAP"</string>
- <string name="account_setup_incoming_imap_path_prefix_hint">"Facoltativo"</string>
- <string name="account_setup_outgoing_title">"Impostazioni server posta in uscita"</string>
- <string name="account_setup_outgoing_smtp_server_label">"Server SMTP"</string>
- <string name="account_setup_outgoing_port_label">"Porta"</string>
- <string name="account_setup_outgoing_security_label">"Tipo di protezione"</string>
- <string name="account_setup_outgoing_require_login_label">"Richiedi accesso"</string>
- <string name="account_setup_outgoing_username_label">"Nome utente"</string>
- <string name="account_setup_outgoing_password_label">"Password"</string>
- <string name="account_setup_options_title">"Opzioni account"</string>
- <string name="account_setup_options_mail_check_frequency_label">"Frequenza di controllo email"</string>
- <string name="account_setup_options_mail_check_frequency_never">"Mai"</string>
- <string name="account_setup_options_mail_check_frequency_5min">"Ogni 5 minuti"</string>
- <string name="account_setup_options_mail_check_frequency_10min">"Ogni 10 minuti"</string>
- <string name="account_setup_options_mail_check_frequency_15min">"Ogni 15 minuti"</string>
- <string name="account_setup_options_mail_check_frequency_30min">"Ogni 30 minuti"</string>
- <string name="account_setup_options_mail_check_frequency_1hour">"Ogni ora"</string>
- <string name="account_setup_options_default_label">"Invia email da questo account per impostazione predefinita."</string>
- <string name="account_setup_options_notify_label">"Avvisami all\'arrivo di email."</string>
- <string name="account_setup_failed_dlg_title">"Impossibile completare l\'impostazione"</string>
- <string name="account_setup_failed_dlg_auth_message">"Nome utente o password errata."</string>
- <string name="account_setup_failed_dlg_auth_message_fmt">"Nome utente o password errata."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_certificate_message">"Impossibile connettersi in modo sicuro al server."</string>
- <string name="account_setup_failed_dlg_certificate_message_fmt">"Impossibile connettersi correttamente al server."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_server_message">"Impossibile connettersi al server."</string>
- <string name="account_setup_failed_dlg_server_message_fmt">"Impossibile connettersi al server."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_tls_required">"TLS richiesto ma non supportato dal server."</string>
- <string name="account_setup_failed_auth_required">"I metodi di autenticazione non sono supportati dal server."</string>
- <string name="account_setup_failed_security">"Impossibile aprire la connessione al server a causa di un errore di protezione."</string>
- <string name="account_setup_failed_ioerror">"Impossibile aprire la connessione al server."</string>
- <string name="account_setup_failed_dlg_edit_details_action">"Modifica dettagli"</string>
- <string name="account_settings_title_fmt">"Impostazioni generali"</string>
- <string name="account_settings_default_label">"Account predefinito"</string>
- <string name="account_settings_default_summary">"Invia email da questo account per impostazione predefinita"</string>
- <string name="account_settings_notify_label">"Notifiche email"</string>
- <string name="account_settings_notify_summary">"Notifica sulla barra di stato l\'arrivo di email"</string>
- <string name="account_settings_mail_check_frequency_label">"Frequenza di controllo email"</string>
- <string name="account_settings_incoming_label">"Impostazioni posta in arrivo"</string>
- <string name="account_settings_outgoing_label">"Impostazioni posta in uscita"</string>
- <string name="account_settings_add_account_label">"Aggiungi un altro account"</string>
- <string name="account_settings_description_label">"Nome account"</string>
- <string name="account_settings_name_label">"Nome"</string>
- <string name="account_settings_notifications">"Impostazioni notifica"</string>
- <string name="account_settings_vibrate_enable">"Vibrazione"</string>
- <string name="account_settings_vibrate_summary">"Attiva anche vibrazione all\'arrivo di email"</string>
- <string name="account_settings_ringtone">"Seleziona suoneria"</string>
- <string name="account_settings_servers">"Impostazioni server"</string>
- <string name="account_delete_dlg_title">"Rimuovi account"</string>
- <string name="account_delete_dlg_instructions_fmt">"L\'account \"<xliff:g id="ACCOUNT">%s</xliff:g>\" verrà rimosso da Email."</string>
- <string name="provider_note_yahoo">"Accesso alla casella di posta non supportato per alcuni tipi di account di posta Yahoo!. Se hai problemi di connessione, visita il sito yahoo.com per ulteriori informazioni."</string>
- <string name="provider_note_yahoo_uk">"Prima di impostare questo account email, visita il sito web Yahoo! e attiva l\'accesso email POP3 per questo account."</string>
- <string name="provider_note_live">"Solo alcuni account \"Plus\" includono l\'accesso POP che consente la connessione del programma. Se non riesci ad accedere con l\'indirizzo email e la password corretti, potresti non disporre di un account \"Plus\" a pagamento. Avvia il browser web per avere accesso a questi account di posta."</string>
- <string name="provider_note_t_online">"Prima di impostare questo account email, visita il sito web T-Online e crea una password per l\'accesso email POP3."</string>
-</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
deleted file mode 100644
index 3aca655c0..000000000
--- a/res/values-ja/strings.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="read_attachment_label">"ãƒ¡ãƒ¼ãƒ«ã®æ·»ä»˜ãƒ•ァイルを読ã¿å–ã‚‹"</string>
- <string name="read_attachment_desc">"ãƒ¡ãƒ¼ãƒ«ã®æ·»ä»˜ãƒ•ァイルã®è¡¨ç¤ºã‚’ã“ã®ã‚¢ãƒ—リケーションã«è¨±å¯ã—ã¾ã™ã€‚"</string>
- <string name="app_name">"メール"</string>
- <string name="accounts_title">"アカウント"</string>
- <string name="compose_title">"作æˆ"</string>
- <string name="debug_title">"デãƒãƒƒã‚°"</string>
- <string name="next_action">"次ã¸"</string>
- <string name="okay_action">"OK"</string>
- <string name="cancel_action">"キャンセル"</string>
- <string name="send_action">"é€ä¿¡"</string>
- <string name="reply_action">"返信"</string>
- <string name="reply_all_action">"全員ã«è¿”ä¿¡"</string>
- <string name="delete_action">"削除"</string>
- <string name="forward_action">"転é€"</string>
- <string name="done_action">"完了"</string>
- <string name="discard_action">"破棄"</string>
- <string name="save_draft_action">"下書ãã¨ã—ã¦ä¿å­˜"</string>
- <string name="refresh_action">"æ›´æ–°"</string>
- <string name="add_account_action">"アカウントを追加"</string>
- <string name="compose_action">"作æˆ"</string>
- <string name="search_action">"検索"</string>
- <string name="open_action">"é–‹ã"</string>
- <string name="account_settings_action">"アカウントã®è¨­å®š"</string>
- <string name="remove_account_action">"アカウントを削除"</string>
- <string name="accounts_action">"アカウント"</string>
- <string name="mark_as_read_action">"既読ã«ã™ã‚‹"</string>
- <string name="mark_as_unread_action">"未読ã«ã™ã‚‹"</string>
- <string name="add_cc_bcc_action">"Cc/Bccを追加"</string>
- <string name="add_attachment_action">"添付ファイルを追加"</string>
- <string name="dump_settings_action">"ダンプ設定"</string>
- <string name="accounts_context_menu_title">"アカウントã®ã‚ªãƒ—ション"</string>
- <string name="status_loading_more">"メールを読ã¿è¾¼ã¿ä¸­..."</string>
- <string name="status_network_error">"接続エラー"</string>
- <string name="status_loading_more_failed">"追加ã®ãƒ¡ãƒ¼ãƒ«ã‚’読ã¿è¾¼ã¿ç›´ã™"</string>
- <string name="notification_new_title">"æ–°ç€ãƒ¡ãƒ¼ãƒ«"</string>
- <string name="notification_new_one_account_fmt">"未読<xliff:g id="UNREAD_MESSAGE_COUNT">%d</xliff:g>件 (<xliff:g id="ACCOUNT">%s</xliff:g>)"</string>
- <string name="notification_new_multi_account_fmt">"(<xliff:g id="NUMBER_ACCOUNTS">%d</xliff:g>個ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆï¼‰"</string>
- <string name="special_mailbox_name_inbox">"å—信トレイ"</string>
- <string name="accounts_welcome">"メールアカウントã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—"\n\n"ãŠå¥½ããªãƒ¡ãƒ¼ãƒ«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’登録ã—ã¦ãã ã•ã„。"\n\n"ç”»é¢ã®æ‰‹é †ã«æ²¿ã£ã¦ç°¡å˜ã«è¿½åŠ ã§ãã¾ã™ã€‚"</string>
- <string name="debug_version_fmt">"ãƒãƒ¼ã‚¸ãƒ§ãƒ³: <xliff:g id="VERSION">%s</xliff:g>"</string>
- <string name="debug_enable_debug_logging_label">"追加ã®ãƒ‡ãƒãƒƒã‚°ãƒ­ã‚°ã‚’有効ã«ã—ã¾ã™ã‹ï¼Ÿ"</string>
- <string name="debug_enable_sensitive_logging_label">"デãƒãƒƒã‚°ãƒ­ã‚°ã«å€‹äººæƒ…å ±ã®è¨˜éŒ²ã‚’許å¯ã™ã‚‹ (パスワードãŒãƒ­ã‚°ã«è¡¨ç¤ºã•れるã“ã¨ãŒã‚りã¾ã™)"</string>
- <string name="message_list_load_more_messages_action">"ä»–ã®ãƒ¡ãƒ¼ãƒ«ã‚‚表示"</string>
- <string name="message_compose_to_hint">"To"</string>
- <string name="message_compose_cc_hint">"Cc"</string>
- <string name="message_compose_bcc_hint">"Bcc"</string>
- <string name="message_compose_subject_hint">"ä»¶å"</string>
- <string name="message_compose_fwd_header_fmt">\n\n"-------- å…ƒã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ --------"\n"ä»¶å: <xliff:g id="SUBJECT">%s</xliff:g>"\n"From: <xliff:g id="SENDER">%s</xliff:g>"\n"To: <xliff:g id="TO">%s</xliff:g>"\n"Cc: <xliff:g id="CC_0">%s</xliff:g>"\n\n</string>
- <string name="message_compose_reply_header_fmt">\n\n"<xliff:g id="SENDER">%s</xliff:g>: "\n\n</string>
- <string name="message_compose_quoted_text_label">"å…ƒã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸"</string>
- <string name="message_compose_error_no_recipients">"宛先を入力ã—ã¦ãã ã•ã„。"</string>
- <string name="message_compose_attachments_skipped_toast">"ダウンロードã•れã¦ã„ãªã„添付ファイルã¯è»¢é€ã§ãã¾ã›ã‚“。"</string>
- <string name="message_view_to_label">"To:"</string>
- <string name="message_view_cc_label">"Cc:"</string>
- <string name="message_view_attachment_view_action">"é–‹ã"</string>
- <string name="message_view_attachment_download_action">"ä¿å­˜"</string>
- <string name="message_view_prev_action">"å‰ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸"</string>
- <string name="message_view_next_action">"次ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸"</string>
- <string name="message_view_status_attachment_saved">"「<xliff:g id="FILENAME">%s</xliff:g>ã€ã¨ã„ã†åå‰ã§æ·»ä»˜ãƒ•ァイルをSDカードã«ä¿å­˜ã—ã¾ã—ãŸã€‚"</string>
- <string name="message_view_status_attachment_not_saved">"添付ファイルをSDカードã«ä¿å­˜ã§ãã¾ã›ã‚“。"</string>
- <string name="message_view_show_pictures_instructions">"埋ã‚è¾¼ã¾ã‚Œã¦ã„ã‚‹ç”»åƒã‚’見るã«ã¯[ç”»åƒã‚’表示]ã‚’é¸æŠžã—ã¦ãã ã•ã„。"</string>
- <string name="message_view_show_pictures_action">"ç”»åƒã‚’表示"</string>
- <string name="message_view_fetching_attachment_toast">"添付ファイルをå–得中"</string>
- <string name="message_deleted_toast">"メッセージを削除ã—ã¾ã—ãŸã€‚"</string>
- <string name="message_discarded_toast">"メッセージを破棄ã—ã¾ã—ãŸã€‚"</string>
- <string name="message_saved_toast">"メッセージを下書ãã¨ã—ã¦ä¿å­˜ã—ã¾ã—ãŸã€‚"</string>
- <string name="account_setup_basics_title">"メールアカウントã®ç™»éŒ²"</string>
- <string name="account_setup_basics_instructions">"メールã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆæƒ…報を入力:"</string>
- <string name="account_setup_basics_email_hint">"メールアドレス"</string>
- <string name="account_setup_basics_password_hint">"パスワード"</string>
- <string name="account_setup_basics_default_label">"ã„ã¤ã‚‚ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã§ãƒ¡ãƒ¼ãƒ«ã‚’é€ä¿¡ã™ã‚‹"</string>
- <string name="account_setup_basics_manual_setup_action">"手動セットアップ"</string>
- <string name="account_setup_username_password_toast">"有効ãªãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¨ãƒ‘スワードを入力ã—ã¦ãã ã•ã„。"</string>
- <string name="account_setup_check_settings_retr_info_msg">"アカウント情報をå–得中..."</string>
- <string name="account_setup_check_settings_check_incoming_msg">"å—信サーãƒãƒ¼ã®è¨­å®šã‚’確èªä¸­..."</string>
- <string name="account_setup_check_settings_check_outgoing_msg">"é€ä¿¡ã‚µãƒ¼ãƒãƒ¼ã®è¨­å®šã‚’確èªä¸­..."</string>
- <string name="account_setup_check_settings_canceling_msg">"キャンセル中..."</string>
- <string name="account_setup_names_title">"メールアカウントã®ç™»éŒ²"</string>
- <string name="account_setup_names_instructions">"アカウントã®è¨­å®šãŒå®Œäº†ã—ã¾ã—ãŸã€‚"</string>
- <string name="account_setup_names_account_name_label">"アカウントã«åå‰ã‚’付ã‘る(çœç•¥å¯ï¼‰"</string>
- <string name="account_setup_names_user_name_label">"åå‰ (é€ä¿¡ãƒ¡ãƒ¼ãƒ«ã«è¡¨ç¤ºã•れã¾ã™)"</string>
- <string name="account_setup_account_type_title">"æ–°ã—ã„メールアカウントを追加"</string>
- <string name="account_setup_account_type_instructions">"ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ã‚¿ã‚¤ãƒ—"</string>
- <string name="account_setup_account_type_pop_action">"POP3アカウント"</string>
- <string name="account_setup_account_type_imap_action">"IMAPアカウント"</string>
- <string name="account_setup_incoming_title">"å—信サーãƒãƒ¼ã®è¨­å®š"</string>
- <string name="account_setup_incoming_username_label">"ユーザーå"</string>
- <string name="account_setup_incoming_password_label">"パスワード"</string>
- <string name="account_setup_incoming_pop_server_label">"POP3サーãƒãƒ¼"</string>
- <string name="account_setup_incoming_imap_server_label">"IMAPサーãƒãƒ¼"</string>
- <string name="account_setup_incoming_port_label">"ãƒãƒ¼ãƒˆ"</string>
- <string name="account_setup_incoming_security_label">"セキュリティã®ç¨®é¡ž"</string>
- <string name="account_setup_incoming_security_none_label">"ãªã—"</string>
- <string name="account_setup_incoming_security_ssl_optional_label">"SSL (使ãˆã‚‹å ´åˆ)"</string>
- <string name="account_setup_incoming_security_ssl_label">"SSL (常ã«ä½¿ç”¨)"</string>
- <string name="account_setup_incoming_security_tls_optional_label">"TLS (使ãˆã‚‹å ´åˆ)"</string>
- <string name="account_setup_incoming_security_tls_label">"TLS (常ã«ä½¿ç”¨)"</string>
- <string name="account_setup_incoming_delete_policy_label">"サーãƒãƒ¼ã‹ã‚‰ãƒ¡ãƒ¼ãƒ«ã‚’削除"</string>
- <string name="account_setup_incoming_delete_policy_never_label">"削除ã—ãªã„"</string>
- <string name="account_setup_incoming_delete_policy_7days_label">"7日後"</string>
- <string name="account_setup_incoming_delete_policy_delete_label">"å—信トレイã‹ã‚‰å‰Šé™¤ã—ãŸã¨ã"</string>
- <string name="account_setup_incoming_imap_path_prefix_label">"IMAPパスã®ãƒ—レフィックス"</string>
- <string name="account_setup_incoming_imap_path_prefix_hint">"çœç•¥å¯"</string>
- <string name="account_setup_outgoing_title">"é€ä¿¡ã‚µãƒ¼ãƒãƒ¼ã®è¨­å®š"</string>
- <string name="account_setup_outgoing_smtp_server_label">"SMTPサーãƒãƒ¼"</string>
- <string name="account_setup_outgoing_port_label">"ãƒãƒ¼ãƒˆ"</string>
- <string name="account_setup_outgoing_security_label">"セキュリティã®ç¨®é¡ž"</string>
- <string name="account_setup_outgoing_require_login_label">"ログインãŒå¿…è¦"</string>
- <string name="account_setup_outgoing_username_label">"ユーザーå"</string>
- <string name="account_setup_outgoing_password_label">"パスワード"</string>
- <string name="account_setup_options_title">"アカウントã®ã‚ªãƒ—ション"</string>
- <string name="account_setup_options_mail_check_frequency_label">"メールãƒã‚§ãƒƒã‚¯ã®é »åº¦"</string>
- <string name="account_setup_options_mail_check_frequency_never">"ãªã—"</string>
- <string name="account_setup_options_mail_check_frequency_5min">"5分毎"</string>
- <string name="account_setup_options_mail_check_frequency_10min">"10分毎"</string>
- <string name="account_setup_options_mail_check_frequency_15min">"15分毎"</string>
- <string name="account_setup_options_mail_check_frequency_30min">"30分毎"</string>
- <string name="account_setup_options_mail_check_frequency_1hour">"1時間毎"</string>
- <string name="account_setup_options_default_label">"ã„ã¤ã‚‚ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã§ãƒ¡ãƒ¼ãƒ«ã‚’é€ä¿¡ã™ã‚‹"</string>
- <string name="account_setup_options_notify_label">"メールã®ç€ä¿¡ã‚’知らã›ã‚‹"</string>
- <string name="account_setup_failed_dlg_title">"セットアップã§ãã¾ã›ã‚“ã§ã—ãŸ"</string>
- <string name="account_setup_failed_dlg_auth_message">"ユーザーåã‹ãƒ‘スワードãŒé–“é•ã£ã¦ã„ã¾ã™ã€‚"</string>
- <string name="account_setup_failed_dlg_auth_message_fmt">"ユーザーåã‹ãƒ‘スワードãŒé–“é•ã£ã¦ã„ã¾ã™ã€‚"\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_certificate_message">"サーãƒãƒ¼ã¸ã®å®‰å…¨ãªæŽ¥ç¶šã‚’確立ã§ãã¾ã›ã‚“。"</string>
- <string name="account_setup_failed_dlg_certificate_message_fmt">"サーãƒãƒ¼ã¸ã®å®‰å…¨ãªæŽ¥ç¶šã‚’確立ã§ãã¾ã›ã‚“。"\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_server_message">"サーãƒãƒ¼ã«æŽ¥ç¶šã§ãã¾ã›ã‚“。"</string>
- <string name="account_setup_failed_dlg_server_message_fmt">"サーãƒãƒ¼ã«æŽ¥ç¶šã§ãã¾ã›ã‚“。"\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_tls_required">"TLSãŒå¿…è¦ã§ã™ãŒã‚µãƒ¼ãƒãƒ¼ãŒå¯¾å¿œã—ã¦ã„ã¾ã›ã‚“。"</string>
- <string name="account_setup_failed_auth_required">"èªè¨¼æ–¹æ³•ãŒã‚µãƒ¼ãƒãƒ¼ã§ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“。"</string>
- <string name="account_setup_failed_security">"セキュリティエラーã®ãŸã‚サーãƒãƒ¼ã«æŽ¥ç¶šã§ãã¾ã›ã‚“。"</string>
- <string name="account_setup_failed_ioerror">"サーãƒãƒ¼ã«æŽ¥ç¶šã§ãã¾ã›ã‚“。"</string>
- <string name="account_setup_failed_dlg_edit_details_action">"設定を編集"</string>
- <string name="account_settings_title_fmt">"全般設定"</string>
- <string name="account_settings_default_label">"既定ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆ"</string>
- <string name="account_settings_default_summary">"ã„ã¤ã‚‚ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã§ãƒ¡ãƒ¼ãƒ«ã‚’é€ä¿¡ã™ã‚‹"</string>
- <string name="account_settings_notify_label">"メール通知"</string>
- <string name="account_settings_notify_summary">"メールã®ç€ä¿¡ã‚’ステータスãƒãƒ¼ã§çŸ¥ã‚‰ã›ã‚‹"</string>
- <string name="account_settings_mail_check_frequency_label">"メールãƒã‚§ãƒƒã‚¯ã®é »åº¦"</string>
- <string name="account_settings_incoming_label">"å—信設定"</string>
- <string name="account_settings_outgoing_label">"é€ä¿¡è¨­å®š"</string>
- <string name="account_settings_add_account_label">"別ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’追加"</string>
- <string name="account_settings_description_label">"アカウントå"</string>
- <string name="account_settings_name_label">"åå‰"</string>
- <string name="account_settings_notifications">"通知設定"</string>
- <string name="account_settings_vibrate_enable">"ãƒã‚¤ãƒ–レーション"</string>
- <string name="account_settings_vibrate_summary">"メールå—ä¿¡: ãƒã‚¤ãƒ–レーションもON"</string>
- <string name="account_settings_ringtone">"ç€ä¿¡éŸ³ã‚’é¸æŠž"</string>
- <string name="account_settings_servers">"サーãƒãƒ¼ã®è¨­å®š"</string>
- <string name="account_delete_dlg_title">"アカウントを削除"</string>
- <string name="account_delete_dlg_instructions_fmt">"アカウント「<xliff:g id="ACCOUNT">%s</xliff:g>ã€ã‚’メールã‹ã‚‰å‰Šé™¤ã—ã¾ã™ã€‚"</string>
- <string name="provider_note_yahoo">"一部ã®ã‚¿ã‚¤ãƒ—ã® Yahoo! メール アカウントã§ã¯ã€å—信トレイã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“。接続ã§ããªã„å ´åˆã¯ yahoo.com ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦è©³ç´°ã‚’ã”確èªãã ã•ã„。"</string>
- <string name="provider_note_yahoo_uk">"ã“ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’設定ã™ã‚‹å‰ã«ã€Yahoo!サイトã§ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®POP3メールアクセスを有効ã«ã—ã¦ãã ã•ã„。"</string>
- <string name="provider_note_live">"ã“ã®ãƒ—ログラムã§POPアクセスãŒè¨±å¯ã•れã¦ã„ã‚‹ã®ã¯ä¸€éƒ¨ã®ã€ŒPlusã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã ã‘ã§ã™ã€‚有料ã®ã€ŒPlusã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒãªã‘れã°ã€æ­£ã—ã„メールアドレスã¨ãƒ‘スワードを入力ã—ã¦ã‚‚ログインã§ãã¾ã›ã‚“。ã“れらã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ã¯ãƒ–ラウザã‹ã‚‰ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ãã ã•ã„。"</string>
- <string name="provider_note_t_online">"ã“ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’設定ã™ã‚‹å‰ã«ã€T-Onlineサイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦POP3メール アクセスã«ä½¿ç”¨ã™ã‚‹ãƒ‘スワードを作æˆã—ã¦ãã ã•ã„。"</string>
-</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
deleted file mode 100644
index 1baa57482..000000000
--- a/res/values-ko/strings.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="read_attachment_label">"ì´ë©”ì¼ ì²¨ë¶€íŒŒì¼ ì½ê¸°"</string>
- <string name="read_attachment_desc">"ì´ ì‘용프로그램으로 ì´ë©”ì¼ ì²¨ë¶€íŒŒì¼ì„ ì½ì„ 수 있습니다."</string>
- <string name="app_name">"ì´ë©”ì¼"</string>
- <string name="accounts_title">"ì‚¬ìš©ìž ê³„ì •"</string>
- <string name="compose_title">"편지쓰기"</string>
- <string name="debug_title">"디버그"</string>
- <string name="next_action">"다ìŒ"</string>
- <string name="okay_action">"확ì¸"</string>
- <string name="cancel_action">"취소"</string>
- <string name="send_action">"보내기"</string>
- <string name="reply_action">"답장"</string>
- <string name="reply_all_action">"전체답장"</string>
- <string name="delete_action">"삭제"</string>
- <string name="forward_action">"전달"</string>
- <string name="done_action">"완료"</string>
- <string name="discard_action">"삭제"</string>
- <string name="save_draft_action">"임시 저장"</string>
- <string name="refresh_action">"새로고침"</string>
- <string name="add_account_action">"계정 추가"</string>
- <string name="compose_action">"편지쓰기"</string>
- <string name="search_action">"검색"</string>
- <string name="open_action">"열기"</string>
- <string name="account_settings_action">"계정 설정"</string>
- <string name="remove_account_action">"계정 삭제"</string>
- <string name="accounts_action">"계정"</string>
- <string name="mark_as_read_action">"ì½ì€ ìƒíƒœë¡œ 표시"</string>
- <string name="mark_as_unread_action">"ì½ì§€ì•Šì€ ìƒíƒœë¡œ 표시"</string>
- <string name="add_cc_bcc_action">"참조 ë° ìˆ¨ì€ì°¸ì¡° 추가"</string>
- <string name="add_attachment_action">"ì²¨ë¶€íŒŒì¼ ì¶”ê°€"</string>
- <string name="dump_settings_action">"ë¤í”„ 설정"</string>
- <string name="accounts_context_menu_title">"계정 옵션"</string>
- <string name="status_loading_more">"ë©”ì¼ ë¡œë“œ 중..."</string>
- <string name="status_network_error">"연결 오류"</string>
- <string name="status_loading_more_failed">"추가 ë©”ì¼ ë¡œë“œ 재시ë„"</string>
- <string name="notification_new_title">"새 ì´ë©”ì¼"</string>
- <string name="notification_new_one_account_fmt">"ì½ì§€ì•Šì€ ë©”ì¼ <xliff:g id="UNREAD_MESSAGE_COUNT">%d</xliff:g>ê°œ(<xliff:g id="ACCOUNT">%s</xliff:g>)"</string>
- <string name="notification_new_multi_account_fmt">"<xliff:g id="NUMBER_ACCOUNTS">%d</xliff:g>개 계정"</string>
- <string name="special_mailbox_name_inbox">"ë°›ì€íŽ¸ì§€í•¨"</string>
- <string name="accounts_welcome">"ì´ë©”ì¼ ì„¤ì •ì— ì˜¤ì‹  ê²ƒì„ í™˜ì˜í•©ë‹ˆë‹¤."\n\n"ì›í•˜ëŠ” ì´ë©”ì¼ ê³„ì •ì„ ì‚¬ìš©í•˜ì„¸ìš”."\n\n"가장 ë§Žì´ ì‚¬ìš©í•˜ëŠ” ì´ë©”ì¼ ê³„ì •ì€ 2단계 ë§Œì— ì„¤ì •í•  수 있습니다."</string>
- <string name="debug_version_fmt">"버전: <xliff:g id="VERSION">%s</xliff:g>"</string>
- <string name="debug_enable_debug_logging_label">"별ë„ì˜ ë””ë²„ê·¸ 로깅 사용 여부"</string>
- <string name="debug_enable_sensitive_logging_label">"디버그 로깅 시 중요 ì •ë³´ 표시 여부(ë¡œê·¸ì— ë¹„ë°€ë²ˆí˜¸ê°€ í‘œì‹œë  ìˆ˜ 있ìŒ)"</string>
- <string name="message_list_load_more_messages_action">"추가 ë©”ì¼ ë¡œë“œ"</string>
- <string name="message_compose_to_hint">"받는사람"</string>
- <string name="message_compose_cc_hint">"참조"</string>
- <string name="message_compose_bcc_hint">"숨ì€ì°¸ì¡°"</string>
- <string name="message_compose_subject_hint">"제목"</string>
- <string name="message_compose_fwd_header_fmt">\n\n"-------- ì›ë³¸ ë©”ì¼ --------"\n"제목: <xliff:g id="SUBJECT">%s</xliff:g>"\n"보낸사람: <xliff:g id="SENDER">%s</xliff:g>"\n"받는사람: <xliff:g id="TO">%s</xliff:g>"\n"참조: <xliff:g id="CC_0">%s</xliff:g>"\n\n</string>
- <string name="message_compose_reply_header_fmt">\n\n"<xliff:g id="SENDER">%s</xliff:g>ë‹˜ì´ ìž‘ì„±:"\n\n</string>
- <string name="message_compose_quoted_text_label">"ë°›ì€ë©”ì¼"</string>
- <string name="message_compose_error_no_recipients">"받는 ì‚¬ëžŒì„ í•œ 명 ì´ìƒ 추가해야 합니다."</string>
- <string name="message_compose_attachments_skipped_toast">"ì¼ë¶€ 첨부파ì¼ì´ 다운로드ë˜ì§€ 않아 전달할 수 없습니다."</string>
- <string name="message_view_to_label">"받는사람:"</string>
- <string name="message_view_cc_label">"참조:"</string>
- <string name="message_view_attachment_view_action">"열기"</string>
- <string name="message_view_attachment_download_action">"저장"</string>
- <string name="message_view_prev_action">"ì´ì „ ë©”ì¼"</string>
- <string name="message_view_next_action">"ë‹¤ìŒ ë©”ì¼"</string>
- <string name="message_view_status_attachment_saved">"첨부파ì¼(<xliff:g id="FILENAME">%s</xliff:g>)ì´ SD ì¹´ë“œì— ì €ìž¥ë˜ì—ˆìŠµë‹ˆë‹¤."</string>
- <string name="message_view_status_attachment_not_saved">"SD ì¹´ë“œì— ì²¨ë¶€íŒŒì¼ì„ 저장할 수 없습니다."</string>
- <string name="message_view_show_pictures_instructions">"ì‚½ìž…ëœ ì‚¬ì§„ì„ í‘œì‹œí•˜ë ¤ë©´ \'사진 표시\'를 ì„ íƒí•˜ì„¸ìš”."</string>
- <string name="message_view_show_pictures_action">"사진 표시"</string>
- <string name="message_view_fetching_attachment_toast">"첨부파ì¼ì„ 가져오는 중입니다."</string>
- <string name="message_deleted_toast">"ë©”ì¼ì´ ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤."</string>
- <string name="message_discarded_toast">"ë©”ì¼ì´ ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤."</string>
- <string name="message_saved_toast">"ë©”ì¼ì„ 임시로 저장했습니다."</string>
- <string name="account_setup_basics_title">"ì´ë©”ì¼ ì„¤ì •"</string>
- <string name="account_setup_basics_instructions">"계정 ì´ë©”ì¼ ì£¼ì†Œ ìž…ë ¥:"</string>
- <string name="account_setup_basics_email_hint">"ì´ë©”ì¼ ì£¼ì†Œ"</string>
- <string name="account_setup_basics_password_hint">"비밀번호"</string>
- <string name="account_setup_basics_default_label">"기본ì ìœ¼ë¡œ ì´ ê³„ì •ì—서 ì´ë©”ì¼ ì „ì†¡"</string>
- <string name="account_setup_basics_manual_setup_action">"ìˆ˜ë™ ì„¤ì •"</string>
- <string name="account_setup_username_password_toast">"올바른 ì´ë©”ì¼ ì£¼ì†Œì™€ 비밀번호를 입력하세요."</string>
- <string name="account_setup_check_settings_retr_info_msg">"계정 정보 검색 중..."</string>
- <string name="account_setup_check_settings_check_incoming_msg">"받는 서버 설정 í™•ì¸ ì¤‘..."</string>
- <string name="account_setup_check_settings_check_outgoing_msg">"보내는 서버 설정 í™•ì¸ ì¤‘..."</string>
- <string name="account_setup_check_settings_canceling_msg">"취소하는 중..."</string>
- <string name="account_setup_names_title">"ì´ë©”ì¼ ì„¤ì •"</string>
- <string name="account_setup_names_instructions">"ê³„ì •ì´ ì„¤ì •ë˜ì—ˆìœ¼ë©° ì´ë©”ì¼ì´ ìž‘ë™ë©ë‹ˆë‹¤."</string>
- <string name="account_setup_names_account_name_label">"계정 ì´ë¦„ ìž…ë ¥(ì„ íƒì‚¬í•­)"</string>
- <string name="account_setup_names_user_name_label">"발신 ë©”ì¼ì— 표시할 ì´ë¦„"</string>
- <string name="account_setup_account_type_title">"새 ì´ë©”ì¼ ê³„ì • 추가"</string>
- <string name="account_setup_account_type_instructions">"계정 유형"</string>
- <string name="account_setup_account_type_pop_action">"POP3 계정"</string>
- <string name="account_setup_account_type_imap_action">"IMAP 계정"</string>
- <string name="account_setup_incoming_title">"받는 서버 설정"</string>
- <string name="account_setup_incoming_username_label">"ì‚¬ìš©ìž ì´ë¦„"</string>
- <string name="account_setup_incoming_password_label">"비밀번호"</string>
- <string name="account_setup_incoming_pop_server_label">"POP3 서버"</string>
- <string name="account_setup_incoming_imap_server_label">"IMAP 서버"</string>
- <string name="account_setup_incoming_port_label">"í¬íЏ"</string>
- <string name="account_setup_incoming_security_label">"보안 유형"</string>
- <string name="account_setup_incoming_security_none_label">"ì—†ìŒ"</string>
- <string name="account_setup_incoming_security_ssl_optional_label">"SSL(제공ë˜ëŠ” 경우)"</string>
- <string name="account_setup_incoming_security_ssl_label">"SSL(í•­ìƒ)"</string>
- <string name="account_setup_incoming_security_tls_optional_label">"TLS(제공ë˜ëŠ” 경우)"</string>
- <string name="account_setup_incoming_security_tls_label">"TLS(í•­ìƒ)"</string>
- <string name="account_setup_incoming_delete_policy_label">"서버ì—서 ì´ë©”ì¼ ì‚­ì œ"</string>
- <string name="account_setup_incoming_delete_policy_never_label">"삭제 안함"</string>
- <string name="account_setup_incoming_delete_policy_7days_label">"7ì¼ í›„"</string>
- <string name="account_setup_incoming_delete_policy_delete_label">"ë°›ì€íŽ¸ì§€í•¨ì—서 삭제할 때"</string>
- <string name="account_setup_incoming_imap_path_prefix_label">"IMAP 경로 ì ‘ë‘ì–´(prefix)"</string>
- <string name="account_setup_incoming_imap_path_prefix_hint">"ì„ íƒì‚¬í•­"</string>
- <string name="account_setup_outgoing_title">"보내는 서버 설정"</string>
- <string name="account_setup_outgoing_smtp_server_label">"SMTP 서버"</string>
- <string name="account_setup_outgoing_port_label">"í¬íЏ"</string>
- <string name="account_setup_outgoing_security_label">"보안 유형"</string>
- <string name="account_setup_outgoing_require_login_label">"로그ì¸í•´ì•¼ 함"</string>
- <string name="account_setup_outgoing_username_label">"ì‚¬ìš©ìž ì´ë¦„"</string>
- <string name="account_setup_outgoing_password_label">"비밀번호"</string>
- <string name="account_setup_options_title">"계정 옵션"</string>
- <string name="account_setup_options_mail_check_frequency_label">"ì´ë©”ì¼ í™•ì¸ ë¹ˆë„"</string>
- <string name="account_setup_options_mail_check_frequency_never">"안함"</string>
- <string name="account_setup_options_mail_check_frequency_5min">"5분마다"</string>
- <string name="account_setup_options_mail_check_frequency_10min">"10분마다"</string>
- <string name="account_setup_options_mail_check_frequency_15min">"15분마다"</string>
- <string name="account_setup_options_mail_check_frequency_30min">"30분마다"</string>
- <string name="account_setup_options_mail_check_frequency_1hour">"1시간마다"</string>
- <string name="account_setup_options_default_label">"기본ì ìœ¼ë¡œ ì´ ê³„ì •ì—서 ì´ë©”ì¼ ì „ì†¡"</string>
- <string name="account_setup_options_notify_label">"ì´ë©”ì¼ ë„ì°© 시 알림"</string>
- <string name="account_setup_failed_dlg_title">"ì„¤ì •ì„ ì™„ë£Œí•  수 ì—†ìŒ"</string>
- <string name="account_setup_failed_dlg_auth_message">"ì‚¬ìš©ìž ì´ë¦„ ë˜ëŠ” 비밀번호가 잘못ë˜ì—ˆìŠµë‹ˆë‹¤."</string>
- <string name="account_setup_failed_dlg_auth_message_fmt">"ìž˜ëª»ëœ ì‚¬ìš©ìž ì´ë¦„ ë˜ëŠ” 비밀번호"\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_certificate_message">"ì„œë²„ì— ì•ˆì „í•˜ê²Œ ì—°ê²°í•  수 없습니다."</string>
- <string name="account_setup_failed_dlg_certificate_message_fmt">"ì„œë²„ì— ì•ˆì „í•˜ê²Œ ì—°ê²°í•  수 없습니다."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_server_message">"ì„œë²„ì— ì—°ê²°í•  수 없습니다."</string>
- <string name="account_setup_failed_dlg_server_message_fmt">"ì„œë²„ì— ì—°ê²°í•  수 없습니다."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_tls_required">"TLSê°€ 필요하지만 서버ì—서 ì§€ì›í•˜ì§€ 않습니다."</string>
- <string name="account_setup_failed_auth_required">"ì¸ì¦ ë°©ë²•ì´ ì„œë²„ì—서 ì§€ì›ë˜ì§€ 않습니다."</string>
- <string name="account_setup_failed_security">"보안 오류로 ì„œë²„ì— ì—°ê²°í•  수 없습니다."</string>
- <string name="account_setup_failed_ioerror">"ì„œë²„ì— ì—°ê²°í•  수 없습니다."</string>
- <string name="account_setup_failed_dlg_edit_details_action">"세부정보 수정"</string>
- <string name="account_settings_title_fmt">"기본설정"</string>
- <string name="account_settings_default_label">"기본 계정"</string>
- <string name="account_settings_default_summary">"기본ì ìœ¼ë¡œ ì´ ê³„ì •ì—서 ì´ë©”ì¼ ì „ì†¡"</string>
- <string name="account_settings_notify_label">"ì´ë©”ì¼ ì•Œë¦¼"</string>
- <string name="account_settings_notify_summary">"ì´ë©”ì¼ ë„ì°© 시 ìƒíƒœ 표시줄ì—서 알림"</string>
- <string name="account_settings_mail_check_frequency_label">"ì´ë©”ì¼ í™•ì¸ ë¹ˆë„"</string>
- <string name="account_settings_incoming_label">"수신 설정"</string>
- <string name="account_settings_outgoing_label">"발신 설정"</string>
- <string name="account_settings_add_account_label">"다른 계정 추가"</string>
- <string name="account_settings_description_label">"계정 ì´ë¦„"</string>
- <string name="account_settings_name_label">"ì´ë¦„"</string>
- <string name="account_settings_notifications">"알림 설정"</string>
- <string name="account_settings_vibrate_enable">"ì§„ë™"</string>
- <string name="account_settings_vibrate_summary">"ì´ë©”ì¼ ë„ì°© 시 ì§„ë™"</string>
- <string name="account_settings_ringtone">"벨소리 ì„ íƒ"</string>
- <string name="account_settings_servers">"서버 설정"</string>
- <string name="account_delete_dlg_title">"계정 삭제"</string>
- <string name="account_delete_dlg_instructions_fmt">"계정(<xliff:g id="ACCOUNT">%s</xliff:g>)ì´ ì´ë©”ì¼ì—서 ì‚­ì œë©ë‹ˆë‹¤."</string>
- <string name="provider_note_yahoo">"ì¼ë¶€ Yahoo! ë©”ì¼ ê³„ì •ì˜ ê²½ìš° íŽ¸ì§€í•¨ì— ì•¡ì„¸ìŠ¤í•  수 없습니다. ì ‘ì†ì— 문제가 ìžˆì„ ê²½ìš° ìžì„¸í•œ 정보는 yahoo.comì„ ì°¸ì¡°í•˜ì„¸ìš”."</string>
- <string name="provider_note_yahoo_uk">"ì´ë©”ì¼ ê³„ì •ì„ ì„¤ì •í•˜ê¸° ì „ì— Yahoo! 웹사ì´íŠ¸ë¥¼ 방문하여 ì´ ê³„ì •ì— ëŒ€í•œ POP3 ì´ë©”ì¼ ì•¡ì„¸ìŠ¤ë¥¼ 사용 설정하세요."</string>
- <string name="provider_note_live">"ì¼ë¶€ \'Plus\' 계정ì—ë§Œ ì´ í”„ë¡œê·¸ëž¨ì„ ì—°ê²°í•  수 있는 POP 액세스 ê¶Œí•œì´ ìžˆìŠµë‹ˆë‹¤. 올바른 ì´ë©”ì¼ ì£¼ì†Œì™€ 비밀번호를 ìž…ë ¥í•´ë„ ë¡œê·¸ì¸ì´ ë˜ì§€ 않으면 \'Plus\' 계정 사용료가 미납ë˜ì—ˆì„ 수 있습니다. ì´ëŸ¬í•œ ë©”ì¼ ê³„ì •ì— ì•¡ì„¸ìŠ¤í•˜ë ¤ë©´ 웹브ë¼ìš°ì €ë¥¼ 실행하세요."</string>
- <string name="provider_note_t_online">"ì´ë©”ì¼ ê³„ì •ì„ ì„¤ì •í•˜ê¸° ì „ì— T-Online 웹사ì´íŠ¸ë¥¼ 방문하여 POP3 ì´ë©”ì¼ ì•¡ì„¸ìŠ¤ì— ëŒ€í•œ 비밀번호를 만드세요."</string>
-</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
deleted file mode 100644
index eed6d4c2a..000000000
--- a/res/values-nb/strings.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="read_attachment_label">"lese e-post-vedlegg"</string>
- <string name="read_attachment_desc">"Tillat applikasjonen å lese e-post-vedleggene dine."</string>
- <string name="app_name">"E-post"</string>
- <string name="accounts_title">"Dine kontoer"</string>
- <string name="compose_title">"Skriv e-post"</string>
- <string name="debug_title">"Debug"</string>
- <string name="next_action">"Neste"</string>
- <string name="okay_action">"OK"</string>
- <string name="cancel_action">"Avbryt"</string>
- <string name="send_action">"Send"</string>
- <string name="reply_action">"Svar"</string>
- <string name="reply_all_action">"Svar alle"</string>
- <string name="delete_action">"Slett"</string>
- <string name="forward_action">"Videresend"</string>
- <string name="done_action">"Ferdig"</string>
- <string name="discard_action">"Forkast"</string>
- <string name="save_draft_action">"Lagre som utkast"</string>
- <string name="refresh_action">"Oppdater"</string>
- <string name="add_account_action">"Legg til konto"</string>
- <string name="compose_action">"Skriv e-post"</string>
- <string name="search_action">"Søk"</string>
- <string name="open_action">"Ã…pne"</string>
- <string name="account_settings_action">"Kontoinnstillinger"</string>
- <string name="remove_account_action">"Fjern konto"</string>
- <string name="accounts_action">"Kontoer"</string>
- <string name="mark_as_read_action">"Merk som lest"</string>
- <string name="mark_as_unread_action">"Merk som ulest"</string>
- <string name="add_cc_bcc_action">"Legg til kopi/blindkopi"</string>
- <string name="add_attachment_action">"Legg til vedlegg"</string>
- <string name="dump_settings_action">"Dump settings"</string>
- <string name="accounts_context_menu_title">"Kontoinnstillinger"</string>
- <string name="status_loading_more">"Henter meldinger…"</string>
- <string name="status_network_error">"Feil ved tilkobling"</string>
- <string name="status_loading_more_failed">"Prøv på nytt å hente flere meldinger"</string>
- <string name="notification_new_title">"Ny e-post"</string>
- <string name="notification_new_one_account_fmt">"<xliff:g id="UNREAD_MESSAGE_COUNT">%d</xliff:g> ulest(e) (<xliff:g id="ACCOUNT">%s</xliff:g>)"</string>
- <string name="notification_new_multi_account_fmt">"i <xliff:g id="NUMBER_ACCOUNTS">%d</xliff:g> kontoer"</string>
- <string name="special_mailbox_name_inbox">"Innboks"</string>
- <string name="accounts_welcome">"Velkommen til e-post-oppsettet!"\n\n"Du kan bruke hvilken som helst e-postkonto."\n\n"De fleste vanlige e-postkontoer kan settes opp i to trinn!"</string>
- <string name="debug_version_fmt">"Version: <xliff:g id="VERSION">%s</xliff:g>"</string>
- <string name="debug_enable_debug_logging_label">"Enable extra debug logging?"</string>
- <string name="debug_enable_sensitive_logging_label">"Enable sensitive information debug logging? (May show passwords in logs.)"</string>
- <string name="message_list_load_more_messages_action">"Hent flere meldinger"</string>
- <string name="message_compose_to_hint">"Til"</string>
- <string name="message_compose_cc_hint">"Kopi"</string>
- <string name="message_compose_bcc_hint">"Blindkopi"</string>
- <string name="message_compose_subject_hint">"Emne"</string>
- <string name="message_compose_fwd_header_fmt">\n\n"-------- Original Message --------"\n"Subject: <xliff:g id="SUBJECT">%s</xliff:g>"\n"From: <xliff:g id="SENDER">%s</xliff:g>"\n"To: <xliff:g id="TO">%s</xliff:g>"\n"CC: <xliff:g id="CC_0">%s</xliff:g>"\n\n</string>
- <string name="message_compose_reply_header_fmt">\n\n"<xliff:g id="SENDER">%s</xliff:g>:"\n\n</string>
- <string name="message_compose_quoted_text_label">"Sitert tekst"</string>
- <string name="message_compose_error_no_recipients">"Du må legge til minst én mottager."</string>
- <string name="message_compose_attachments_skipped_toast">"Noen vedlegg kunne ikke sendes videre fordi de ikke er blitt lastet ned."</string>
- <string name="message_view_to_label">"Til:"</string>
- <string name="message_view_cc_label">"Kopi:"</string>
- <string name="message_view_attachment_view_action">"Ã…pne"</string>
- <string name="message_view_attachment_download_action">"Lagre"</string>
- <string name="message_view_prev_action">"Forrige melding"</string>
- <string name="message_view_next_action">"Neste melding"</string>
- <string name="message_view_status_attachment_saved">"Vedlegget ble lagret til minnekortet som <xliff:g id="FILENAME">%s</xliff:g>."</string>
- <string name="message_view_status_attachment_not_saved">"Kunne ikke lagre vedlegget til minnekort."</string>
- <string name="message_view_show_pictures_instructions">"Velg \\\\\\\"Vis bilder\\\\\\\" for å vise vedlagte bilder."</string>
- <string name="message_view_show_pictures_action">"Vis bilder"</string>
- <string name="message_view_fetching_attachment_toast">"Henter vedlegg."</string>
- <string name="message_deleted_toast">"Meldingen ble slettet."</string>
- <string name="message_discarded_toast">"Meldingen ble forkastet."</string>
- <string name="message_saved_toast">"Meldingen ble lagret som utkast."</string>
- <string name="account_setup_basics_title">"Sett opp e-post"</string>
- <string name="account_setup_basics_instructions">"Skriv e-postadressen til kontoen din:"</string>
- <string name="account_setup_basics_email_hint">"E-postadresse"</string>
- <string name="account_setup_basics_password_hint">"Passord"</string>
- <string name="account_setup_basics_default_label">"Bruk denne kontoen som standard for utgående e-post."</string>
- <string name="account_setup_basics_manual_setup_action">"Manuelt oppsett"</string>
- <string name="account_setup_username_password_toast">"Skriv inn en gyldig e-postadresse og passord."</string>
- <string name="account_setup_check_settings_retr_info_msg">"Henter kontoinformasjon…"</string>
- <string name="account_setup_check_settings_check_incoming_msg">"Sjekker tjenerinnstillinger for inngående e-post…"</string>
- <string name="account_setup_check_settings_check_outgoing_msg">"Sjekker tjenerinnstillinger for utgående e-post…"</string>
- <string name="account_setup_check_settings_canceling_msg">"Avbryter…"</string>
- <string name="account_setup_names_title">"Sett opp e-post"</string>
- <string name="account_setup_names_instructions">"Kontoen er satt opp, og e-post er på vei!"</string>
- <string name="account_setup_names_account_name_label">"Gi denne kontoen et navn (valgfritt)"</string>
- <string name="account_setup_names_user_name_label">"Navnet ditt (vises i utgående meldinger)"</string>
- <string name="account_setup_account_type_title">"Legg til ny e-postkonto"</string>
- <string name="account_setup_account_type_instructions">"Hva slags konto er dette?"</string>
- <string name="account_setup_account_type_pop_action">"POP3-konto"</string>
- <string name="account_setup_account_type_imap_action">"IMAP-konto"</string>
- <string name="account_setup_incoming_title">"Tjenerinnstillinger for inngående e-post"</string>
- <string name="account_setup_incoming_username_label">"Brukernavn"</string>
- <string name="account_setup_incoming_password_label">"Passord"</string>
- <string name="account_setup_incoming_pop_server_label">"POP3-tjener"</string>
- <string name="account_setup_incoming_imap_server_label">"IMAP-tjener"</string>
- <string name="account_setup_incoming_port_label">"Port"</string>
- <string name="account_setup_incoming_security_label">"Sikkerhetstype"</string>
- <string name="account_setup_incoming_security_none_label">"Ingen"</string>
- <string name="account_setup_incoming_security_ssl_optional_label">"SSL (hvis tilgjengelig)"</string>
- <string name="account_setup_incoming_security_ssl_label">"SSL (alltid)"</string>
- <string name="account_setup_incoming_security_tls_optional_label">"TLS (hvis tilgjengelig)"</string>
- <string name="account_setup_incoming_security_tls_label">"TLS (alltid)"</string>
- <string name="account_setup_incoming_delete_policy_label">"Slett e-post fra tjener"</string>
- <string name="account_setup_incoming_delete_policy_never_label">"Aldri"</string>
- <string name="account_setup_incoming_delete_policy_7days_label">"Etter en uke"</string>
- <string name="account_setup_incoming_delete_policy_delete_label">"NÃ¥r jeg sletter den fra innboksen"</string>
- <string name="account_setup_incoming_imap_path_prefix_label">"IMAP-stiprefiks"</string>
- <string name="account_setup_incoming_imap_path_prefix_hint">"Valgfritt"</string>
- <string name="account_setup_outgoing_title">"Tjenerinnstillinger for utgående e-post"</string>
- <string name="account_setup_outgoing_smtp_server_label">"SMTP-tjener"</string>
- <string name="account_setup_outgoing_port_label">"Port"</string>
- <string name="account_setup_outgoing_security_label">"Sikkerhetstype"</string>
- <string name="account_setup_outgoing_require_login_label">"Krev innlogging."</string>
- <string name="account_setup_outgoing_username_label">"Brukernavn"</string>
- <string name="account_setup_outgoing_password_label">"Passord"</string>
- <string name="account_setup_options_title">"Kontoinnstillinger"</string>
- <string name="account_setup_options_mail_check_frequency_label">"Hvor ofte e-post skal sjekkes"</string>
- <string name="account_setup_options_mail_check_frequency_never">"Aldri"</string>
- <string name="account_setup_options_mail_check_frequency_5min">"Hvert 5. minutt"</string>
- <string name="account_setup_options_mail_check_frequency_10min">"Hvert 10. minutt"</string>
- <string name="account_setup_options_mail_check_frequency_15min">"Hvert 15. minutt"</string>
- <string name="account_setup_options_mail_check_frequency_30min">"Hvert 30. minutt"</string>
- <string name="account_setup_options_mail_check_frequency_1hour">"Hver time"</string>
- <string name="account_setup_options_default_label">"Bruk denne kontoen som standard for utgående e-post."</string>
- <string name="account_setup_options_notify_label">"Varsle når det kommer e-post."</string>
- <string name="account_setup_failed_dlg_title">"Kunne ikke fullføre oppsettet"</string>
- <string name="account_setup_failed_dlg_auth_message">"Feil brukernavn eller passord."</string>
- <string name="account_setup_failed_dlg_auth_message_fmt">"Feil brukernavn eller passord."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_certificate_message">"Kan ikke åpne en sikker tilkobling til tjeneren."</string>
- <string name="account_setup_failed_dlg_certificate_message_fmt">"Kan ikke åpne en sikker tilkobling til tjeneren."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_server_message">"Kan ikke koble til tjeneren."</string>
- <string name="account_setup_failed_dlg_server_message_fmt">"Kan ikke koble til tjeneren."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_tls_required">"TLS påkrevd, men tjeneren støtter det ikke."</string>
- <string name="account_setup_failed_auth_required">"Tjeneren støtter ikke de påkrevde autentiseringsmetodene."</string>
- <string name="account_setup_failed_security">"Kunne ikke koble til tjeneren på grunn av sikkerhetsfeil."</string>
- <string name="account_setup_failed_ioerror">"Kunne ikke koble til tjeneren."</string>
- <string name="account_setup_failed_dlg_edit_details_action">"Rediger detaljer"</string>
- <string name="account_settings_title_fmt">"Generelle innstillinger"</string>
- <string name="account_settings_default_label">"Standardkonto"</string>
- <string name="account_settings_default_summary">"Bruk denne kontoen som standard for utgående e-post."</string>
- <string name="account_settings_notify_label">"Varsling om e-post"</string>
- <string name="account_settings_notify_summary">"Varsle i statusfeltet når det kommer e-post"</string>
- <string name="account_settings_mail_check_frequency_label">"Hvor ofte det skal sjekkes etter e-post"</string>
- <string name="account_settings_incoming_label">"Inngående innstillinger"</string>
- <string name="account_settings_outgoing_label">"Utgående innstillinger"</string>
- <string name="account_settings_add_account_label">"Legg til en annen konto"</string>
- <string name="account_settings_description_label">"Kontonavn"</string>
- <string name="account_settings_name_label">"Ditt navn"</string>
- <string name="account_settings_notifications">"Innstillinger for varsling"</string>
- <string name="account_settings_vibrate_enable">"Vibrer"</string>
- <string name="account_settings_vibrate_summary">"Vibrer når det kommer e-post"</string>
- <string name="account_settings_ringtone">"Velg ringetone"</string>
- <string name="account_settings_servers">"Innstillinger for tjener"</string>
- <string name="account_delete_dlg_title">"Fjern"</string>
- <string name="account_delete_dlg_instructions_fmt">"Kontoen \\\\\\\"<xliff:g id="ACCOUNT">%s</xliff:g>\\\\\\\" vil bli fjernet fra e-postapplikasjonen."</string>
- <string name="provider_note_yahoo">"E-posttilgang er ikke støttet for enkelte typer Yahoo!-e-postkontoer. Hvis du har problemer med å koble til, besøk yahoo.com for mer informasjon."</string>
- <string name="provider_note_yahoo_uk">"Før du setter opp denne e-postkontoen, må du gå til Yahoo!-nettsiden og slå på POP3-tilgang for den."</string>
- <string name="provider_note_live">"Bare noen \\\\\\\"pluss-kontoer tilbyr POP-tilgangBREAK_0 som dette programmet trenger for å koble til. Hvis du ikke klarer å logge innBREAK_1 med riktig e-postadresse og passord, kan det være du ikke har en betaltBREAK_2 \\\\\\\"pluss-tilgang. Start nettleseren for å få tilgang til slike e-postkontoer."</string>
- <string name="provider_note_t_online">"Før du setter opp denne e-postkontoen, besøk T-Online-nettsiden og velg et passord for e-posttilgang via POP3."</string>
-</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
deleted file mode 100644
index 1d666bea1..000000000
--- a/res/values-nl/strings.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="read_attachment_label">"Bijlages van e-mail lezen"</string>
- <string name="read_attachment_desc">"Staat deze toepassing toe om je E-mail-bijlages te lezen."</string>
- <string name="app_name">"E-mail"</string>
- <string name="accounts_title">"Je accounts"</string>
- <string name="compose_title">"Opstellen"</string>
- <string name="debug_title">"Foutopsporing"</string>
- <string name="next_action">"Volgende"</string>
- <string name="okay_action">"OK"</string>
- <string name="cancel_action">"Annuleren"</string>
- <string name="send_action">"Verzenden"</string>
- <string name="reply_action">"Beantwoorden"</string>
- <string name="reply_all_action">"Allen beantwoorden"</string>
- <string name="delete_action">"Verwijderen"</string>
- <string name="forward_action">"Doorsturen"</string>
- <string name="done_action">"Gereed"</string>
- <string name="discard_action">"Verwijderen"</string>
- <string name="save_draft_action">"Opslaan als concept"</string>
- <string name="refresh_action">"Vernieuwen"</string>
- <string name="add_account_action">"Account toevoegen"</string>
- <string name="compose_action">"Opstellen"</string>
- <string name="search_action">"Zoeken"</string>
- <string name="open_action">"Openen"</string>
- <string name="account_settings_action">"Accountinstellingen"</string>
- <string name="remove_account_action">"Account verwijderen"</string>
- <string name="accounts_action">"Accounts"</string>
- <string name="mark_as_read_action">"Markeren als gelezen"</string>
- <string name="mark_as_unread_action">"Markeren als ongelezen"</string>
- <string name="add_cc_bcc_action">"Cc/Bcc toevoegen"</string>
- <string name="add_attachment_action">"Bijlage toevoegen"</string>
- <string name="dump_settings_action">"Dumpinstellingen"</string>
- <string name="accounts_context_menu_title">"Acountopties"</string>
- <string name="status_loading_more">"Berichten laden..."</string>
- <string name="status_network_error">"Verbindingsfout"</string>
- <string name="status_loading_more_failed">"Probeer opnieuw meer berichten te laden"</string>
- <string name="notification_new_title">"Nieuwe e-mail"</string>
- <string name="notification_new_one_account_fmt">"<xliff:g id="UNREAD_MESSAGE_COUNT">%d</xliff:g> ongelezen (<xliff:g id="ACCOUNT">%s</xliff:g>)"</string>
- <string name="notification_new_multi_account_fmt">"in <xliff:g id="NUMBER_ACCOUNTS">%d</xliff:g> accounts"</string>
- <string name="special_mailbox_name_inbox">"Postvak IN"</string>
- <string name="accounts_welcome">"Welkom bij E-mail instellen."\n\n"Je kunt elke account gebruiken met E-mail."\n\n"De meest populaire e-mailaccounts kunnen in twee stappen worden ingesteld."</string>
- <string name="debug_version_fmt">"Versie: <xliff:g id="VERSION">%s</xliff:g>"</string>
- <string name="debug_enable_debug_logging_label">"Extra logboek voor probleemoplossing bij gevoelige informatie maken?"</string>
- <string name="debug_enable_sensitive_logging_label">"Probleemoplossing bij gevoelige informatie vastleggen? (Mogelijk worden er wachtwoorden weergegeven in de logboeken.)"</string>
- <string name="message_list_load_more_messages_action">"Meer berichten laden"</string>
- <string name="message_compose_to_hint">"Aan"</string>
- <string name="message_compose_cc_hint">"Cc"</string>
- <string name="message_compose_bcc_hint">"Bcc"</string>
- <string name="message_compose_subject_hint">"Onderwerp"</string>
- <string name="message_compose_fwd_header_fmt">\n\n"-------- Oorspronkelijk bericht --------"\n"Onderwerp: <xliff:g id="SUBJECT">%s</xliff:g>"\n"Van: <xliff:g id="SENDER">%s</xliff:g>"\n"Aan: <xliff:g id="TO">%s</xliff:g>"\n"Cc: <xliff:g id="CC_0">%s</xliff:g>"\n\n</string>
- <string name="message_compose_reply_header_fmt">\n\n"<xliff:g id="SENDER">%s</xliff:g>schreef:"\n\n</string>
- <string name="message_compose_quoted_text_label">"Geciteerde tekst"</string>
- <string name="message_compose_error_no_recipients">"Je moet minstens één ontvanger toevoegen."</string>
- <string name="message_compose_attachments_skipped_toast">"Sommige bijlages kunnen niet worden doorgestuurd omdat ze niet zijn gedownload."</string>
- <string name="message_view_to_label">"Aan:"</string>
- <string name="message_view_cc_label">"Cc:"</string>
- <string name="message_view_attachment_view_action">"Openen"</string>
- <string name="message_view_attachment_download_action">"Opslaan"</string>
- <string name="message_view_prev_action">"Vorig bericht"</string>
- <string name="message_view_next_action">"Volgend bericht"</string>
- <string name="message_view_status_attachment_saved">"Bijlage opgeslagen op SD-kaart als <xliff:g id="FILENAME">%s</xliff:g>."</string>
- <string name="message_view_status_attachment_not_saved">"Kan bijlage niet opslaan op SD-kaart."</string>
- <string name="message_view_show_pictures_instructions">"Selecteer Afbeeldingen weergeven om ingevoegde afbeeldingen weer te geven."</string>
- <string name="message_view_show_pictures_action">"Afbeeldingen weergeven"</string>
- <string name="message_view_fetching_attachment_toast">"Bijlage wordt opgehaald."</string>
- <string name="message_deleted_toast">"Bericht verwijderd."</string>
- <string name="message_discarded_toast">"Bericht genegeerd"</string>
- <string name="message_saved_toast">"Bericht opgeslagen als concept."</string>
- <string name="account_setup_basics_title">"E-mail instellen"</string>
- <string name="account_setup_basics_instructions">"Typ het e-mailadres van je account:"</string>
- <string name="account_setup_basics_email_hint">"E-mailadres"</string>
- <string name="account_setup_basics_password_hint">"Wachtwoord"</string>
- <string name="account_setup_basics_default_label">"E-mail standaard vanaf deze account versturen"</string>
- <string name="account_setup_basics_manual_setup_action">"Handmatig instellen"</string>
- <string name="account_setup_username_password_toast">"Typ een geldig e-mailadres en wachtwoord"</string>
- <string name="account_setup_check_settings_retr_info_msg">"Accountinformatie ophalen..."</string>
- <string name="account_setup_check_settings_check_incoming_msg">"Serverinstellingen voor binnenkomende e-mail controleren..."</string>
- <string name="account_setup_check_settings_check_outgoing_msg">"Serverinstellingen voor uitgaande e-mail controleren..."</string>
- <string name="account_setup_check_settings_canceling_msg">"Annuleren..."</string>
- <string name="account_setup_names_title">"E-mail instellen"</string>
- <string name="account_setup_names_instructions">"Je account is ingesteld en er is e-mail onderweg."</string>
- <string name="account_setup_names_account_name_label">"Geef deze account een naam (optioneel)"</string>
- <string name="account_setup_names_user_name_label">"Je naam (wordt weergegeven in uitgaande berichten)"</string>
- <string name="account_setup_account_type_title">"Nieuwe e-mailaccount toevoegen"</string>
- <string name="account_setup_account_type_instructions">"Welk type account is dit?"</string>
- <string name="account_setup_account_type_pop_action">"POP3-account"</string>
- <string name="account_setup_account_type_imap_action">"IMAP-account"</string>
- <string name="account_setup_incoming_title">"Serverinstellingen voor binnenkomende e-mail"</string>
- <string name="account_setup_incoming_username_label">"Gebruikersnaam"</string>
- <string name="account_setup_incoming_password_label">"Wachtwoord"</string>
- <string name="account_setup_incoming_pop_server_label">"POP3-server"</string>
- <string name="account_setup_incoming_imap_server_label">"IMAP-server"</string>
- <string name="account_setup_incoming_port_label">"Port"</string>
- <string name="account_setup_incoming_security_label">"Beveiligingstype"</string>
- <string name="account_setup_incoming_security_none_label">"Geen"</string>
- <string name="account_setup_incoming_security_ssl_optional_label">"SSL (indien beschikbaar)"</string>
- <string name="account_setup_incoming_security_ssl_label">"SSL (altijd)"</string>
- <string name="account_setup_incoming_security_tls_optional_label">"TLS (indien beschikbaar)"</string>
- <string name="account_setup_incoming_security_tls_label">"TLS (altijd)"</string>
- <string name="account_setup_incoming_delete_policy_label">"E-mail verwijderen van server"</string>
- <string name="account_setup_incoming_delete_policy_never_label">"Nooit"</string>
- <string name="account_setup_incoming_delete_policy_7days_label">"Na 7 dagen"</string>
- <string name="account_setup_incoming_delete_policy_delete_label">"Als ik verwijder uit mijn Postvak IN"</string>
- <string name="account_setup_incoming_imap_path_prefix_label">"Voorvoegsel IMAP-pad"</string>
- <string name="account_setup_incoming_imap_path_prefix_hint">"Optioneel"</string>
- <string name="account_setup_outgoing_title">"Serverinstellingen voor uitgaande e-mail"</string>
- <string name="account_setup_outgoing_smtp_server_label">"SMTP-server"</string>
- <string name="account_setup_outgoing_port_label">"Poort"</string>
- <string name="account_setup_outgoing_security_label">"Beveiligingstype"</string>
- <string name="account_setup_outgoing_require_login_label">"Aanmelden vereist"</string>
- <string name="account_setup_outgoing_username_label">"Gebruikersnaam"</string>
- <string name="account_setup_outgoing_password_label">"Wachtwoord"</string>
- <string name="account_setup_options_title">"Accountopties"</string>
- <string name="account_setup_options_mail_check_frequency_label">"Frequentie voor het controleren op nieuwe berichten"</string>
- <string name="account_setup_options_mail_check_frequency_never">"Nooit"</string>
- <string name="account_setup_options_mail_check_frequency_5min">"Elke 5 minuten"</string>
- <string name="account_setup_options_mail_check_frequency_10min">"Elke 10 minuten"</string>
- <string name="account_setup_options_mail_check_frequency_15min">"Elke 15 minuten"</string>
- <string name="account_setup_options_mail_check_frequency_30min">"Elke 30 minuten"</string>
- <string name="account_setup_options_mail_check_frequency_1hour">"Elk uur"</string>
- <string name="account_setup_options_default_label">"E-mail standaard vanaf deze account versturen"</string>
- <string name="account_setup_options_notify_label">"Stuur me een melding wanneer er e-mail binnenkomt."</string>
- <string name="account_setup_failed_dlg_title">"Instellen is niet voltooid"</string>
- <string name="account_setup_failed_dlg_auth_message">"Gebruikersnaam of wachtwoord onjuist"</string>
- <string name="account_setup_failed_dlg_auth_message_fmt">"Gebruikersnaam of wachtwoord is onjuist."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_certificate_message">"Kan geen veilige verbinding met de server maken."</string>
- <string name="account_setup_failed_dlg_certificate_message_fmt">"Kan geen veilige verbinding met de server tot stand brengen."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_server_message">"Kan geen verbinding maken met de server."</string>
- <string name="account_setup_failed_dlg_server_message_fmt">"Kan geen verbinding maken met de server."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_tls_required">"TLS is vereist maar wordt niet ondersteund door de server."</string>
- <string name="account_setup_failed_auth_required">"Verificatiemethoden worden niet ondersteund door de server."</string>
- <string name="account_setup_failed_security">"Kan geen verbinding maken met de server wegens een beveiligingsfout."</string>
- <string name="account_setup_failed_ioerror">"Kan geen verbinding met de server maken."</string>
- <string name="account_setup_failed_dlg_edit_details_action">"Details bewerken"</string>
- <string name="account_settings_title_fmt">"Algemene instellingen"</string>
- <string name="account_settings_default_label">"Standaardaccount"</string>
- <string name="account_settings_default_summary">"E-mail standaard vanaf deze account versturen"</string>
- <string name="account_settings_notify_label">"Meldingen via e-mail"</string>
- <string name="account_settings_notify_summary">"Melding in statusbalk wanneer er e-mail binnenkomt"</string>
- <string name="account_settings_mail_check_frequency_label">"Frequentie voor het controleren op nieuwe e-mail"</string>
- <string name="account_settings_incoming_label">"Instellingen voor binnenkomende e-mail"</string>
- <string name="account_settings_outgoing_label">"Instellingen voor uitgaande e-mail"</string>
- <string name="account_settings_add_account_label">"Nieuwe account toevoegen"</string>
- <string name="account_settings_description_label">"Accountnaam"</string>
- <string name="account_settings_name_label">"Je naam"</string>
- <string name="account_settings_notifications">"Instellingen voor meldingen"</string>
- <string name="account_settings_vibrate_enable">"Trillen"</string>
- <string name="account_settings_vibrate_summary">"Ook trillen bij ontvangst van e-mail"</string>
- <string name="account_settings_ringtone">"Beltoon selecteren"</string>
- <string name="account_settings_servers">"Serverinstellingen"</string>
- <string name="account_delete_dlg_title">"Account verwijderen"</string>
- <string name="account_delete_dlg_instructions_fmt">"De account <xliff:g id="ACCOUNT">%s</xliff:g> wordt verwijderd van E-mail"</string>
- <string name="provider_note_yahoo">"Toegang tot postvakken wordt niet ondersteund door sommige typen Yahoo!-mailaccounts. Als er problemen ontstaan bij het verbinden, ga je naar yahoo.com voor meer informatie."</string>
- <string name="provider_note_yahoo_uk">"Ga voordat je deze e-mailaccount instelt naar de website van Yahoo! en schakel toegang met POP3 in voor deze account."</string>
- <string name="provider_note_live">"Alleen sommige Plus-accounts hebben POP-toegang waarmee dit programma verbinding kan maken. Als je je niet kunt aanmelden met het juiste e-mailadres en wachtwoord, heb je mogelijk niet betaald voor je Plus-account. Start de webbrowser voor toegang tot deze e-mailaccounts."</string>
- <string name="provider_note_t_online">"Voordat je deze e-mailaccount instelt, ga je naar de website van T-Online en maak je een wachtwoord voor toegang tot e-mail via POP3."</string>
-</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
deleted file mode 100644
index 456de9709..000000000
--- a/res/values-pl/strings.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="read_attachment_label">"odczyt załączników w wiadomościach e-mail"</string>
- <string name="read_attachment_desc">"Umożliwia tej aplikacji odczyt załączników poczty e-mail."</string>
- <string name="app_name">"Poczta e-mail"</string>
- <string name="accounts_title">"Twoje konta"</string>
- <string name="compose_title">"Utwórz"</string>
- <string name="debug_title">"Debuguj"</string>
- <string name="next_action">"Dalej"</string>
- <string name="okay_action">"OK"</string>
- <string name="cancel_action">"Anuluj"</string>
- <string name="send_action">"Wyślij"</string>
- <string name="reply_action">"Odpowiedz"</string>
- <string name="reply_all_action">"Odpowiedz wszystkim"</string>
- <string name="delete_action">"Usuń"</string>
- <string name="forward_action">"Przekaż dalej"</string>
- <string name="done_action">"Gotowe"</string>
- <string name="discard_action">"Odrzuć"</string>
- <string name="save_draft_action">"Zapisz jako wersjÄ™ roboczÄ…"</string>
- <string name="refresh_action">"Odśwież"</string>
- <string name="add_account_action">"Dodaj konto"</string>
- <string name="compose_action">"Utwórz"</string>
- <string name="search_action">"Szukaj"</string>
- <string name="open_action">"Otwórz"</string>
- <string name="account_settings_action">"Ustawienia konta"</string>
- <string name="remove_account_action">"Usuń konto"</string>
- <string name="accounts_action">"Konta"</string>
- <string name="mark_as_read_action">"Oznacz jako przeczytane"</string>
- <string name="mark_as_unread_action">"Oznacz jako nieprzeczytane"</string>
- <string name="add_cc_bcc_action">"Dodaj DW/UDW"</string>
- <string name="add_attachment_action">"Dodaj załącznik"</string>
- <string name="dump_settings_action">"Zrzut ustawień"</string>
- <string name="accounts_context_menu_title">"Opcje konta"</string>
- <string name="status_loading_more">"Åadowanie wiadomoÅ›ci…"</string>
- <string name="status_network_error">"Błąd połączenia"</string>
- <string name="status_loading_more_failed">"Ponów próbę załadowania większej liczby wiadomości"</string>
- <string name="notification_new_title">"Nowa wiadomość e-mail"</string>
- <string name="notification_new_one_account_fmt">"Nieprzeczytane: <xliff:g id="UNREAD_MESSAGE_COUNT">%d</xliff:g> (<xliff:g id="ACCOUNT">%s</xliff:g>)"</string>
- <string name="notification_new_multi_account_fmt">"na <xliff:g id="NUMBER_ACCOUNTS">%d</xliff:g> kontach"</string>
- <string name="special_mailbox_name_inbox">"Odebrane"</string>
- <string name="accounts_welcome">"Witamy w konfiguracji poczty e-mail!"\n\n"W tej usłudze można korzystać z dowolnego konta e-mail."\n\n"Konfiguracja najpopularniejszych kont e-mail składa się z tylko 2 etapów."</string>
- <string name="debug_version_fmt">"Wersja: <xliff:g id="VERSION">%s</xliff:g>"</string>
- <string name="debug_enable_debug_logging_label">"Czy włączyć dodatkowe rejestrowanie na potrzeby debugowania?"</string>
- <string name="debug_enable_sensitive_logging_label">"Czy chcesz włączyć rejestrowanie poufnych informacji na potrzeby debugowania? (Może to spowodować uwzględnianie haseł w dziennikach)."</string>
- <string name="message_list_load_more_messages_action">"Załaduj więcej wiadomości"</string>
- <string name="message_compose_to_hint">"Do"</string>
- <string name="message_compose_cc_hint">"DW"</string>
- <string name="message_compose_bcc_hint">"UDW"</string>
- <string name="message_compose_subject_hint">"Temat"</string>
- <string name="message_compose_fwd_header_fmt">\n\n"-------- Wiadomość oryginalna --------"\n"Temat: <xliff:g id="SUBJECT">%s</xliff:g>"\n"Od: <xliff:g id="SENDER">%s</xliff:g>"\n"Do: <xliff:g id="TO">%s</xliff:g>"\n"DW: <xliff:g id="CC_0">%s</xliff:g>"\n\n</string>
- <string name="message_compose_reply_header_fmt">\n\n"Użytkownik <xliff:g id="SENDER">%s</xliff:g> napisał:"\n\n</string>
- <string name="message_compose_quoted_text_label">"Cytowany tekst"</string>
- <string name="message_compose_error_no_recipients">"Musisz dodać co najmniej jednego adresata."</string>
- <string name="message_compose_attachments_skipped_toast">"Nie można przekazać dalej niektórych załączników, ponieważ nie zostały one pobrane."</string>
- <string name="message_view_to_label">"Do:"</string>
- <string name="message_view_cc_label">"DW:"</string>
- <string name="message_view_attachment_view_action">"Otwórz"</string>
- <string name="message_view_attachment_download_action">"Zapisz"</string>
- <string name="message_view_prev_action">"Poprzednia wiadomość"</string>
- <string name="message_view_next_action">"Następna wiadomość"</string>
- <string name="message_view_status_attachment_saved">"Załącznik został zapisany na karcie SD jako <xliff:g id="FILENAME">%s</xliff:g>."</string>
- <string name="message_view_status_attachment_not_saved">"Nie można zapisać załącznika na karcie SD."</string>
- <string name="message_view_show_pictures_instructions">"Wybierz opcję Pokaż obrazy, aby wyświetlić osadzone obrazy."</string>
- <string name="message_view_show_pictures_action">"Pokaż obrazy"</string>
- <string name="message_view_fetching_attachment_toast">"Pobieranie załącznika."</string>
- <string name="message_deleted_toast">"Wiadomość została usunięta."</string>
- <string name="message_discarded_toast">"Wiadomość została odrzucona."</string>
- <string name="message_saved_toast">"Wiadomość została zapisana jako wersja robocza."</string>
- <string name="account_setup_basics_title">"Skonfiguruj konto e-mail"</string>
- <string name="account_setup_basics_instructions">"Podaj adres e-mail swojego konta:"</string>
- <string name="account_setup_basics_email_hint">"Adres e-mail"</string>
- <string name="account_setup_basics_password_hint">"Hasło"</string>
- <string name="account_setup_basics_default_label">"Domyślnie wysyłaj wiadomości e-mail z tego konta"</string>
- <string name="account_setup_basics_manual_setup_action">"Konfiguracja ręczna"</string>
- <string name="account_setup_username_password_toast">"Podaj prawidłowy adres e-mail i hasło."</string>
- <string name="account_setup_check_settings_retr_info_msg">"Pobieranie informacji o koncie…"</string>
- <string name="account_setup_check_settings_check_incoming_msg">"Sprawdzanie ustawień serwera poczty przychodzącej…"</string>
- <string name="account_setup_check_settings_check_outgoing_msg">"Sprawdzanie ustawień serwera poczty wychodzącej…"</string>
- <string name="account_setup_check_settings_canceling_msg">"Anulowanie…"</string>
- <string name="account_setup_names_title">"Konfiguracja konta e-mail"</string>
- <string name="account_setup_names_instructions">"Konto zostało skonfigurowane, a wiadomości e-mail są w drodze!"</string>
- <string name="account_setup_names_account_name_label">"Nazwa konta (opcjonalnie)"</string>
- <string name="account_setup_names_user_name_label">"Twoje nazwisko (wyświetlane w wiadomościach wychodzących)"</string>
- <string name="account_setup_account_type_title">"Dodaj nowe konto e-mail"</string>
- <string name="account_setup_account_type_instructions">"Jakiego typu jest to konto?"</string>
- <string name="account_setup_account_type_pop_action">"Konto POP3"</string>
- <string name="account_setup_account_type_imap_action">"Konto IMAP"</string>
- <string name="account_setup_incoming_title">"Ustawienia serwera poczty przychodzÄ…cej"</string>
- <string name="account_setup_incoming_username_label">"Nazwa użytkownika"</string>
- <string name="account_setup_incoming_password_label">"Hasło"</string>
- <string name="account_setup_incoming_pop_server_label">"Serwer POP3"</string>
- <string name="account_setup_incoming_imap_server_label">"Serwer IMAP"</string>
- <string name="account_setup_incoming_port_label">"Port"</string>
- <string name="account_setup_incoming_security_label">"Typ zabezpieczeń"</string>
- <string name="account_setup_incoming_security_none_label">"Brak"</string>
- <string name="account_setup_incoming_security_ssl_optional_label">"SSL (jeśli dostępne)"</string>
- <string name="account_setup_incoming_security_ssl_label">"SSL (zawsze)"</string>
- <string name="account_setup_incoming_security_tls_optional_label">"TLS (jeśli dostępne)"</string>
- <string name="account_setup_incoming_security_tls_label">"TLS (zawsze)"</string>
- <string name="account_setup_incoming_delete_policy_label">"Usuń wiadomości e-mail z serwera"</string>
- <string name="account_setup_incoming_delete_policy_never_label">"Nigdy"</string>
- <string name="account_setup_incoming_delete_policy_7days_label">"Po 7 dniach"</string>
- <string name="account_setup_incoming_delete_policy_delete_label">"Po usunięciu z folderu Odebrane"</string>
- <string name="account_setup_incoming_imap_path_prefix_label">"Prefiks ścieżki IMAP"</string>
- <string name="account_setup_incoming_imap_path_prefix_hint">"Opcjonalnie"</string>
- <string name="account_setup_outgoing_title">"Ustawienia serwera poczty wychodzÄ…cej"</string>
- <string name="account_setup_outgoing_smtp_server_label">"Serwer SMTP"</string>
- <string name="account_setup_outgoing_port_label">"Port"</string>
- <string name="account_setup_outgoing_security_label">"Typ zabezpieczeń"</string>
- <string name="account_setup_outgoing_require_login_label">"Wymagaj zalogowania siÄ™."</string>
- <string name="account_setup_outgoing_username_label">"Nazwa użytkownika"</string>
- <string name="account_setup_outgoing_password_label">"Hasło"</string>
- <string name="account_setup_options_title">"Opcje konta"</string>
- <string name="account_setup_options_mail_check_frequency_label">"Częstotliwość sprawdzania poczty e-mail"</string>
- <string name="account_setup_options_mail_check_frequency_never">"Nigdy"</string>
- <string name="account_setup_options_mail_check_frequency_5min">"Co 5 minut"</string>
- <string name="account_setup_options_mail_check_frequency_10min">"Co 10 minut"</string>
- <string name="account_setup_options_mail_check_frequency_15min">"Co 15 minut"</string>
- <string name="account_setup_options_mail_check_frequency_30min">"Co 30 minut"</string>
- <string name="account_setup_options_mail_check_frequency_1hour">"Co godzinÄ™"</string>
- <string name="account_setup_options_default_label">"Domyślnie wysyłaj wiadomości e-mail z tego konta"</string>
- <string name="account_setup_options_notify_label">"Powiadom mnie o odebranej poczcie e-mail."</string>
- <string name="account_setup_failed_dlg_title">"Nie można zakończyć konfiguracji"</string>
- <string name="account_setup_failed_dlg_auth_message">"Nieprawidłowa nazwa użytkownika lub hasło."</string>
- <string name="account_setup_failed_dlg_auth_message_fmt">"Nieprawidłowa nazwa użytkownika lub hasło."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_certificate_message">"Nie można nawiązać bezpiecznego połączenia z serwerem."</string>
- <string name="account_setup_failed_dlg_certificate_message_fmt">"Nie można nawiązać bezpiecznego połączenia z serwerem."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_server_message">"Nie można nawiązać połączenia z serwerem."</string>
- <string name="account_setup_failed_dlg_server_message_fmt">"Nie można nawiązać połączenia z serwerem."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_tls_required">"Wymagane połączenie TLS nie jest obsługiwane przez serwer."</string>
- <string name="account_setup_failed_auth_required">"Serwer nie obsługuje metod uwierzytelniania."</string>
- <string name="account_setup_failed_security">"Nie można nawiązać połączenia z serwerem z powodu błędu zabezpieczeń."</string>
- <string name="account_setup_failed_ioerror">"Nie można nawiązać połączenia z serwerem."</string>
- <string name="account_setup_failed_dlg_edit_details_action">"Edytuj szczegóły"</string>
- <string name="account_settings_title_fmt">"Ustawienia ogólne"</string>
- <string name="account_settings_default_label">"Domyślne konto"</string>
- <string name="account_settings_default_summary">"Domyślnie wysyłaj wiadomości e-mail z tego konta"</string>
- <string name="account_settings_notify_label">"Powiadomienia e-mail"</string>
- <string name="account_settings_notify_summary">"Wyświetl powiadomienie na pasku stanu po otrzymaniu wiadomości e-mail"</string>
- <string name="account_settings_mail_check_frequency_label">"Częstotliwość sprawdzania poczty e-mail"</string>
- <string name="account_settings_incoming_label">"Ustawienia poczty przychodzÄ…cej"</string>
- <string name="account_settings_outgoing_label">"Ustawienia poczty wychodzÄ…cej"</string>
- <string name="account_settings_add_account_label">"Dodaj kolejne konto"</string>
- <string name="account_settings_description_label">"Nazwa konta"</string>
- <string name="account_settings_name_label">"ImiÄ™ i nazwisko"</string>
- <string name="account_settings_notifications">"Ustawienia powiadomień"</string>
- <string name="account_settings_vibrate_enable">"Wibracje"</string>
- <string name="account_settings_vibrate_summary">"Sygnalizuj wibracjami otrzymanie wiadomości e-mail"</string>
- <string name="account_settings_ringtone">"Wybierz dzwonek"</string>
- <string name="account_settings_servers">"Ustawienia serwera"</string>
- <string name="account_delete_dlg_title">"Usuń konto"</string>
- <string name="account_delete_dlg_instructions_fmt">"Konto <xliff:g id="ACCOUNT">%s</xliff:g> zostanie usunięte z usługi poczty e-mail."</string>
- <string name="provider_note_yahoo">"Dostęp do skrzynki pocztowej nie jest obsługiwany w przypadku kilku typów kont pocztowych w usłudze Yahoo! Jeśli podczas nawiązywania połączenia występują problemy, odwiedź witrynę yahoo.com w celu uzyskania dodatkowych informacji."</string>
- <string name="provider_note_yahoo_uk">"Przed skonfigurowaniem tego konta e-mail odwiedź witrynę usługi Yahoo! i włącz dostęp do poczty POP3."</string>
- <string name="provider_note_live">"Tylko niektóre konta typu Plus zawierają funkcję dostępu POP, która umożliwia nawiązywanie połączenia za pomocą tego programu. Jeśli nie możesz zalogować się przy użyciu poprawnego adresu e-mail i hasła, to być może nie posiadasz płatnego konta typu Plus. Uruchom przeglądarkę internetową, aby uzyskać dostęp do tych kont pocztowych."</string>
- <string name="provider_note_t_online">"Przed skonfigurowaniem tego konta e-mail odwiedź witrynę usługi T-Online i utwórz hasło na potrzeby dostępu do poczty POP3."</string>
-</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
deleted file mode 100644
index 8b0f7aec1..000000000
--- a/res/values-ru/strings.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="read_attachment_label">"чтение почтовых приложений"</string>
- <string name="read_attachment_desc">"ПозволÑет данной программе читать ваши почтовые приложениÑ."</string>
- <string name="app_name">"Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð¿Ð¾Ñ‡Ñ‚Ð°"</string>
- <string name="accounts_title">"Ваши аккаунты"</string>
- <string name="compose_title">"ÐапиÑать пиÑьмо"</string>
- <string name="debug_title">"Отладка"</string>
- <string name="next_action">"Далее"</string>
- <string name="okay_action">"ОК"</string>
- <string name="cancel_action">"Отмена"</string>
- <string name="send_action">"Отправить"</string>
- <string name="reply_action">"Ответить"</string>
- <string name="reply_all_action">"Ответить вÑем"</string>
- <string name="delete_action">"Удалить"</string>
- <string name="forward_action">"ПереÑлать"</string>
- <string name="done_action">"Готово"</string>
- <string name="discard_action">"Отменить"</string>
- <string name="save_draft_action">"Сохранить как черновик"</string>
- <string name="refresh_action">"Обновить"</string>
- <string name="add_account_action">"Добавить аккаунт"</string>
- <string name="compose_action">"ÐапиÑать пиÑьмо"</string>
- <string name="search_action">"ПоиÑк"</string>
- <string name="open_action">"Открыть"</string>
- <string name="account_settings_action">"ÐаÑтройки аккаунта"</string>
- <string name="remove_account_action">"Удалить аккаунт"</string>
- <string name="accounts_action">"Ðккаунты"</string>
- <string name="mark_as_read_action">"Отметить как прочитанное"</string>
- <string name="mark_as_unread_action">"Отметить как непрочитанное"</string>
- <string name="add_cc_bcc_action">"Добавить копии/Ñкрытые копии"</string>
- <string name="add_attachment_action">"Добавить приложение"</string>
- <string name="dump_settings_action">"ÐаÑтройки ÑброÑа"</string>
- <string name="accounts_context_menu_title">"Параметры аккаунта"</string>
- <string name="status_loading_more">"Загрузка пиÑем..."</string>
- <string name="status_network_error">"Ошибка подключениÑ"</string>
- <string name="status_loading_more_failed">"Повторить попытку загрузки оÑтальных пиÑем"</string>
- <string name="notification_new_title">"Ðовое пиÑьмо"</string>
- <string name="notification_new_one_account_fmt">"Ðепрочитанных: <xliff:g id="UNREAD_MESSAGE_COUNT">%d</xliff:g> (<xliff:g id="ACCOUNT">%s</xliff:g>)"</string>
- <string name="notification_new_multi_account_fmt">"в неÑкольких (<xliff:g id="NUMBER_ACCOUNTS">%d</xliff:g>) аккаунтах"</string>
- <string name="special_mailbox_name_inbox">"ВходÑщие"</string>
- <string name="accounts_welcome">"Добро пожаловать на Ñтраницу наÑтройки Ñлектронной почты."\n\n"С нашей почтовой ÑиÑтемой можно иÑпользовать любой аккаунт Ñлектронной почты."\n\n"Самые раÑпроÑтраненные аккаунты Ñлектронной почты можно наÑтроить за 2 шага."</string>
- <string name="debug_version_fmt">"ВерÑиÑ: <xliff:g id="VERSION">%s</xliff:g>"</string>
- <string name="debug_enable_debug_logging_label">"Включить ведение журнала раÑширенной отладки?"</string>
- <string name="debug_enable_sensitive_logging_label">"Включить ведение журнала отладки Ð´Ð»Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð´ÐµÐ½Ñ†Ð¸Ð°Ð»ÑŒÐ½Ð¾Ð¹ информации? (Ð’ журналах могут быть показаны пароли.)"</string>
- <string name="message_list_load_more_messages_action">"Загрузить еще пиÑьма"</string>
- <string name="message_compose_to_hint">"Кому"</string>
- <string name="message_compose_cc_hint">"КопиÑ"</string>
- <string name="message_compose_bcc_hint">"СкрытаÑ"</string>
- <string name="message_compose_subject_hint">"Тема"</string>
- <string name="message_compose_fwd_header_fmt">\n\n"-------- ИÑходное Ñообщение --------"\n"Тема: <xliff:g id="SUBJECT">%s</xliff:g>"\n"От: <xliff:g id="SENDER">%s</xliff:g>"\n"Кому: <xliff:g id="TO">%s</xliff:g>"\n"КопиÑ: <xliff:g id="CC_0">%s</xliff:g>"\n\n</string>
- <string name="message_compose_reply_header_fmt">\n\n"<xliff:g id="SENDER">%s</xliff:g> напиÑал(а):"\n\n</string>
- <string name="message_compose_quoted_text_label">"Цитируемый текÑÑ‚"</string>
- <string name="message_compose_error_no_recipients">"Ðеобходимо добавить Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одного получателÑ."</string>
- <string name="message_compose_attachments_skipped_toast">"Ðекоторые Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿ÐµÑ€ÐµÑлать, поÑкольку они не загружены."</string>
- <string name="message_view_to_label">"Кому:"</string>
- <string name="message_view_cc_label">"КопиÑ:"</string>
- <string name="message_view_attachment_view_action">"Открыть"</string>
- <string name="message_view_attachment_download_action">"Сохранить"</string>
- <string name="message_view_prev_action">"Пред. пиÑьмо"</string>
- <string name="message_view_next_action">"След. пиÑьмо"</string>
- <string name="message_view_status_attachment_saved">"Приложение Ñохранено на SD-карту как <xliff:g id="FILENAME">%s</xliff:g>."</string>
- <string name="message_view_status_attachment_not_saved">"Ðе удаетÑÑ Ñохранить приложение на SD-карту."</string>
- <string name="message_view_show_pictures_instructions">"Выберите \"Показать картинки\", чтобы показать вÑтроенную графику."</string>
- <string name="message_view_show_pictures_action">"Показать картинки"</string>
- <string name="message_view_fetching_attachment_toast">"Загрузка приложениÑ."</string>
- <string name="message_deleted_toast">"ПиÑьмо удалено."</string>
- <string name="message_discarded_toast">"ПиÑьмо не Ñохранено."</string>
- <string name="message_saved_toast">"ПиÑьмо Ñохранено как черновик."</string>
- <string name="account_setup_basics_title">"ÐаÑтройка Ñлектронной почты"</string>
- <string name="account_setup_basics_instructions">"Укажите почтовый Ð°Ð´Ñ€ÐµÑ Ñвоего аккаунта:"</string>
- <string name="account_setup_basics_email_hint">"ÐÐ´Ñ€ÐµÑ Ñлектронной почты"</string>
- <string name="account_setup_basics_password_hint">"Пароль"</string>
- <string name="account_setup_basics_default_label">"По умолчанию отправлÑть почту Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ аккаунта."</string>
- <string name="account_setup_basics_manual_setup_action">"Ð ÑƒÑ‡Ð½Ð°Ñ Ð½Ð°Ñтройка"</string>
- <string name="account_setup_username_password_toast">"Укажите правильные Ð°Ð´Ñ€ÐµÑ Ñлектронной почты и пароль."</string>
- <string name="account_setup_check_settings_retr_info_msg">"Получение информации об аккаунте..."</string>
- <string name="account_setup_check_settings_check_incoming_msg">"Проверка наÑтроек Ñервера входÑщей почты..."</string>
- <string name="account_setup_check_settings_check_outgoing_msg">"Проверка наÑтроек Ñервера иÑходÑщей почты..."</string>
- <string name="account_setup_check_settings_canceling_msg">"Отмена..."</string>
- <string name="account_setup_names_title">"ÐаÑтройка Ñлектронной почты"</string>
- <string name="account_setup_names_instructions">"Ваш аккаунт наÑтроен, ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð¿Ð¾Ñ‡Ñ‚Ð° работает."</string>
- <string name="account_setup_names_account_name_label">"Указать название Ñтого аккаунта (необÑзательно)"</string>
- <string name="account_setup_names_user_name_label">"Ваше Ð¸Ð¼Ñ (отображаетÑÑ Ð² иÑходÑщих пиÑьмах)"</string>
- <string name="account_setup_account_type_title">"Добавить новый аккаунт Ñлектронной почты"</string>
- <string name="account_setup_account_type_instructions">"К какому типу принадлежит Ñтот аккаунт?"</string>
- <string name="account_setup_account_type_pop_action">"Ðккаунт POP3"</string>
- <string name="account_setup_account_type_imap_action">"Ðккаунт IMAP"</string>
- <string name="account_setup_incoming_title">"ÐаÑтройки Ñервера входÑщей почты"</string>
- <string name="account_setup_incoming_username_label">"Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"</string>
- <string name="account_setup_incoming_password_label">"Пароль"</string>
- <string name="account_setup_incoming_pop_server_label">"Сервер POP3"</string>
- <string name="account_setup_incoming_imap_server_label">"Сервер IMAP"</string>
- <string name="account_setup_incoming_port_label">"Порт"</string>
- <string name="account_setup_incoming_security_label">"Тип безопаÑноÑти"</string>
- <string name="account_setup_incoming_security_none_label">"Ðет"</string>
- <string name="account_setup_incoming_security_ssl_optional_label">"SSL (еÑли доÑтупен)"</string>
- <string name="account_setup_incoming_security_ssl_label">"SSL (вÑегда)"</string>
- <string name="account_setup_incoming_security_tls_optional_label">"TLS (еÑли доÑтупно)"</string>
- <string name="account_setup_incoming_security_tls_label">"TLS (вÑегда)"</string>
- <string name="account_setup_incoming_delete_policy_label">"Удалить пиÑьмо Ñ Ñервера"</string>
- <string name="account_setup_incoming_delete_policy_never_label">"Ðикогда"</string>
- <string name="account_setup_incoming_delete_policy_7days_label">"Через 7 дней"</string>
- <string name="account_setup_incoming_delete_policy_delete_label">"При удалении пиÑьма из папки \"ВходÑщие\""</string>
- <string name="account_setup_incoming_imap_path_prefix_label">"ÐŸÑ€ÐµÑ„Ð¸ÐºÑ Ð¿ÑƒÑ‚Ð¸ IMAP"</string>
- <string name="account_setup_incoming_imap_path_prefix_hint">"ÐеобÑзательно"</string>
- <string name="account_setup_outgoing_title">"ÐаÑтройки Ñервера иÑходÑщей почты"</string>
- <string name="account_setup_outgoing_smtp_server_label">"Сервер SMTP"</string>
- <string name="account_setup_outgoing_port_label">"Порт"</string>
- <string name="account_setup_outgoing_security_label">"Тип безопаÑноÑти"</string>
- <string name="account_setup_outgoing_require_login_label">"Требовать входа в ÑиÑтему."</string>
- <string name="account_setup_outgoing_username_label">"Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"</string>
- <string name="account_setup_outgoing_password_label">"Пароль"</string>
- <string name="account_setup_options_title">"Параметры аккаунта"</string>
- <string name="account_setup_options_mail_check_frequency_label">"ЧаÑтота проверки Ñлектронной почты"</string>
- <string name="account_setup_options_mail_check_frequency_never">"Ðикогда"</string>
- <string name="account_setup_options_mail_check_frequency_5min">"Каждые 5 минут"</string>
- <string name="account_setup_options_mail_check_frequency_10min">"Каждые 10 минут"</string>
- <string name="account_setup_options_mail_check_frequency_15min">"Каждые 15 минут"</string>
- <string name="account_setup_options_mail_check_frequency_30min">"Каждые 30 минут"</string>
- <string name="account_setup_options_mail_check_frequency_1hour">"Каждый чаÑ"</string>
- <string name="account_setup_options_default_label">"По умолчанию отправлÑть почту Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ аккаунта."</string>
- <string name="account_setup_options_notify_label">"Оповещать Ð¼ÐµÐ½Ñ Ð¿Ñ€Ð¸ получении почты."</string>
- <string name="account_setup_failed_dlg_title">"Ðе удаетÑÑ Ð·Ð°Ð²ÐµÑ€ÑˆÐ¸Ñ‚ÑŒ уÑтановку"</string>
- <string name="account_setup_failed_dlg_auth_message">"Ðеверное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ неверный пароль."</string>
- <string name="account_setup_failed_dlg_auth_message_fmt">"Ðеверное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ неверный пароль."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_certificate_message">"Ðе удаетÑÑ ÑƒÑтановить защищенное Ñоединение Ñ Ñервером."</string>
- <string name="account_setup_failed_dlg_certificate_message_fmt">"Ðе удаетÑÑ ÑƒÑтановить защищенное Ñоединение Ñ Ñервером."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_server_message">"Ðе удаетÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒÑÑ Ðº Ñерверу."</string>
- <string name="account_setup_failed_dlg_server_message_fmt">"Ðе удаетÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒÑÑ Ðº Ñерверу."\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_tls_required">"TLS требуетÑÑ, но не поддерживаетÑÑ Ñервером."</string>
- <string name="account_setup_failed_auth_required">"Сервер не поддерживает методы аутентификации."</string>
- <string name="account_setup_failed_security">"Ðе удаетÑÑ ÑƒÑтановить Ñоединение Ñ Ñервером из-за ошибки безопаÑноÑти."</string>
- <string name="account_setup_failed_ioerror">"Ðе удаетÑÑ ÑƒÑтановить Ñоединение Ñ Ñервером."</string>
- <string name="account_setup_failed_dlg_edit_details_action">"Изменить подробную информацию"</string>
- <string name="account_settings_title_fmt">"Общие наÑтройки"</string>
- <string name="account_settings_default_label">"Ðккаунт по умолчанию"</string>
- <string name="account_settings_default_summary">"По умолчанию отправлÑть почту Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ аккаунта"</string>
- <string name="account_settings_notify_label">"ÐžÐ¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¾ получении почты"</string>
- <string name="account_settings_notify_summary">"При получении почты показывать оповещение в Ñтроке ÑоÑтоÑниÑ"</string>
- <string name="account_settings_mail_check_frequency_label">"ЧаÑтота проверки Ñлектронной почты"</string>
- <string name="account_settings_incoming_label">"ÐаÑтройки входÑщей почты"</string>
- <string name="account_settings_outgoing_label">"ÐаÑтройки иÑходÑщей почты"</string>
- <string name="account_settings_add_account_label">"Добавить другой аккаунт"</string>
- <string name="account_settings_description_label">"Ðазвание аккаунта"</string>
- <string name="account_settings_name_label">"Ваше имÑ"</string>
- <string name="account_settings_notifications">"ÐаÑтройки оповещениÑ"</string>
- <string name="account_settings_vibrate_enable">"ВибрациÑ"</string>
- <string name="account_settings_vibrate_summary">"Также включить вибрацию при получении почты"</string>
- <string name="account_settings_ringtone">"Выбрать мелодию"</string>
- <string name="account_settings_servers">"ÐаÑтройки Ñервера"</string>
- <string name="account_delete_dlg_title">"Удалить аккаунт"</string>
- <string name="account_delete_dlg_instructions_fmt">"Ðккаунт \"<xliff:g id="ACCOUNT">%s</xliff:g>\" будет удален из ÑиÑтемы Ñлектронной почты."</string>
- <string name="provider_note_yahoo">"ДоÑтуп к почтовому Ñщику Ð´Ð»Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… типов почтовых аккаунтов Yahoo! не поддерживаетÑÑ. ЕÑли при подключении возникли проблемы, Ñм. дополнительные ÑÐ²ÐµÐ´ÐµÐ½Ð¸Ñ Ð½Ð° yahoo.com."</string>
- <string name="provider_note_yahoo_uk">"Чтобы наÑтроить Ñтот аккаунт Ñлектронной почты, перейдите на веб-Ñайт Yahoo! и включите Ð´Ð»Ñ Ñтого аккаунта доÑтуп по протоколу POP3."</string>
- <string name="provider_note_live">"Только некоторые аккаунты \"Plus\" поддерживают доÑтуп по протоколу POP, который требуетÑÑ Ð´Ð°Ð½Ð½Ð¾Ð¹ программе Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ. ЕÑли вам не удаетÑÑ Ð²Ð¾Ð¹Ñ‚Ð¸ в ÑиÑтему Ñ Ð²ÐµÑ€Ð½Ñ‹Ð¼ адреÑом Ñлектронной почты и паролем, возможно, у Ð²Ð°Ñ Ð½ÐµÑ‚ платного аккаунта \"Plus\". Откройте веб-браузер, чтобы получить доÑтуп к Ñтим почтовым аккаунтам."</string>
- <string name="provider_note_t_online">"Чтобы наÑтроить Ñтот аккаунт Ñлектронной почты, перейдите на веб-Ñайт T-Online и Ñоздайте пароль Ð´Ð»Ñ Ð´Ð¾Ñтупа к Ñлектронной почте по протоколу POP3."</string>
-</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
deleted file mode 100644
index d6d57e039..000000000
--- a/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="read_attachment_label">"读å–电å­é‚®ä»¶é™„ä»¶"</string>
- <string name="read_attachment_desc">"å…许此应用程åºè¯»å–您的电å­é‚®ä»¶é™„件。"</string>
- <string name="app_name">"电å­é‚®ä»¶"</string>
- <string name="accounts_title">"æ‚¨çš„å¸æˆ·"</string>
- <string name="compose_title">"撰写"</string>
- <string name="debug_title">"调试"</string>
- <string name="next_action">"下一步"</string>
- <string name="okay_action">"确定"</string>
- <string name="cancel_action">"å–æ¶ˆ"</string>
- <string name="send_action">"å‘é€"</string>
- <string name="reply_action">"回å¤"</string>
- <string name="reply_all_action">"å›žå¤æ‰€æœ‰äºº"</string>
- <string name="delete_action">"删除"</string>
- <string name="forward_action">"转å‘"</string>
- <string name="done_action">"完æˆ"</string>
- <string name="discard_action">"å–æ¶ˆ"</string>
- <string name="save_draft_action">"å¦å­˜ä¸ºè‰ç¨¿"</string>
- <string name="refresh_action">"刷新"</string>
- <string name="add_account_action">"æ·»åŠ å¸æˆ·"</string>
- <string name="compose_action">"撰写"</string>
- <string name="search_action">"æœç´¢"</string>
- <string name="open_action">"打开"</string>
- <string name="account_settings_action">"叿ˆ·è®¾ç½®"</string>
- <string name="remove_account_action">"åˆ é™¤å¸æˆ·"</string>
- <string name="accounts_action">"叿ˆ·"</string>
- <string name="mark_as_read_action">"标记为已读"</string>
- <string name="mark_as_unread_action">"标记为未读"</string>
- <string name="add_cc_bcc_action">"添加抄é€/密é€å¯¹è±¡"</string>
- <string name="add_attachment_action">"添加附件"</string>
- <string name="dump_settings_action">"转存设置"</string>
- <string name="accounts_context_menu_title">"叿ˆ·é€‰é¡¹"</string>
- <string name="status_loading_more">"正在载入邮件..."</string>
- <string name="status_network_error">"连接错误"</string>
- <string name="status_loading_more_failed">"釿–°å°è¯•载入更多邮件"</string>
- <string name="notification_new_title">"新电å­é‚®ä»¶"</string>
- <string name="notification_new_one_account_fmt">"有 <xliff:g id="UNREAD_MESSAGE_COUNT">%d</xliff:g> å°æœªè¯»é‚®ä»¶ (<xliff:g id="ACCOUNT">%s</xliff:g>)"</string>
- <string name="notification_new_multi_account_fmt">"在 <xliff:g id="NUMBER_ACCOUNTS">%d</xliff:g> ä¸ªå¸æˆ·ä¸­"</string>
- <string name="special_mailbox_name_inbox">"æ”¶ä»¶ç®±"</string>
- <string name="accounts_welcome">"欢迎设置电å­é‚®ä»¶ï¼"\n\n"在此å¯ä½¿ç”¨ä»»æ„电å­é‚®ä»¶å¸æˆ·ã€‚"\n\n"大多数常è§çš„电å­é‚®ä»¶å¸æˆ·é€šè¿‡ 2 æ­¥å³å¯å®Œæˆè®¾ç½®ï¼"</string>
- <string name="debug_version_fmt">"版本:<xliff:g id="VERSION">%s</xliff:g>"</string>
- <string name="debug_enable_debug_logging_label">"å¯ç”¨é¢å¤–的调试日志记录?"</string>
- <string name="debug_enable_sensitive_logging_label">"å¯ç”¨æ•感信æ¯è°ƒè¯•日志记录(å¯èƒ½ä¼šåœ¨è®°å½•中显示密ç ï¼‰ï¼Ÿ"</string>
- <string name="message_list_load_more_messages_action">"载入更多邮件"</string>
- <string name="message_compose_to_hint">"收件人"</string>
- <string name="message_compose_cc_hint">"抄é€"</string>
- <string name="message_compose_bcc_hint">"密é€"</string>
- <string name="message_compose_subject_hint">"主题"</string>
- <string name="message_compose_fwd_header_fmt">\n\n"-------- 原始邮件 --------"\n"主题:<xliff:g id="SUBJECT">%s</xliff:g>"\n"å‘件人:<xliff:g id="SENDER">%s</xliff:g>"\n"收件人:<xliff:g id="TO">%s</xliff:g>"\n"抄é€ï¼š<xliff:g id="CC_0">%s</xliff:g>"\n\n</string>
- <string name="message_compose_reply_header_fmt">\n\n"<xliff:g id="SENDER">%s</xliff:g>写é“:"\n\n</string>
- <string name="message_compose_quoted_text_label">"引用文字"</string>
- <string name="message_compose_error_no_recipients">"您必须至少添加一个收件人。"</string>
- <string name="message_compose_attachments_skipped_toast">"æŸäº›é™„件尚未下载,因此无法转å‘。"</string>
- <string name="message_view_to_label">"收件人:"</string>
- <string name="message_view_cc_label">"抄é€ï¼š"</string>
- <string name="message_view_attachment_view_action">"打开"</string>
- <string name="message_view_attachment_download_action">"ä¿å­˜"</string>
- <string name="message_view_prev_action">"上一å°é‚®ä»¶"</string>
- <string name="message_view_next_action">"下一å°é‚®ä»¶"</string>
- <string name="message_view_status_attachment_saved">"附件已ä¿å­˜åˆ° SD å¡ä¸­ï¼Œæ–‡ä»¶å为 <xliff:g id="FILENAME">%s</xliff:g>。"</string>
- <string name="message_view_status_attachment_not_saved">"无法将附件ä¿å­˜åˆ° SD å¡ã€‚"</string>
- <string name="message_view_show_pictures_instructions">"选择“显示图片â€å¯æ˜¾ç¤ºåµŒå…¥çš„图片。"</string>
- <string name="message_view_show_pictures_action">"显示图片"</string>
- <string name="message_view_fetching_attachment_toast">"正在æå–附件。"</string>
- <string name="message_deleted_toast">"邮件已删除。"</string>
- <string name="message_discarded_toast">"邮件已喿¶ˆã€‚"</string>
- <string name="message_saved_toast">"邮件已å¦å­˜ä¸ºè‰ç¨¿ã€‚"</string>
- <string name="account_setup_basics_title">"设置电å­é‚®ä»¶"</string>
- <string name="account_setup_basics_instructions">"é”®å…¥æ‚¨çš„å¸æˆ·ç”µå­é‚®ä»¶åœ°å€ï¼š"</string>
- <string name="account_setup_basics_email_hint">"电å­é‚®ä»¶åœ°å€"</string>
- <string name="account_setup_basics_password_hint">"密ç "</string>
- <string name="account_setup_basics_default_label">"é»˜è®¤æƒ…å†µä¸‹ä»Žè¯¥å¸æˆ·å‘é€ç”µå­é‚®ä»¶ã€‚"</string>
- <string name="account_setup_basics_manual_setup_action">"手动设置"</string>
- <string name="account_setup_username_password_toast">"请键入有效的电å­é‚®ä»¶åœ°å€å’Œå¯†ç ã€‚"</string>
- <string name="account_setup_check_settings_retr_info_msg">"æ­£åœ¨æ£€ç´¢å¸æˆ·ä¿¡æ¯..."</string>
- <string name="account_setup_check_settings_check_incoming_msg">"正在检查接收æœåŠ¡å™¨è®¾ç½®..."</string>
- <string name="account_setup_check_settings_check_outgoing_msg">"æ­£åœ¨æ£€æŸ¥å¤–å‘æœåŠ¡å™¨è®¾ç½®..."</string>
- <string name="account_setup_check_settings_canceling_msg">"æ­£åœ¨å–æ¶ˆ..."</string>
- <string name="account_setup_names_title">"设置电å­é‚®ä»¶"</string>
- <string name="account_setup_names_instructions">"æ‚¨çš„å¸æˆ·è®¾ç½®å®Œæ¯•,å¯ä»¥æ”¶å‘电å­é‚®ä»¶äº†ï¼"</string>
- <string name="account_setup_names_account_name_label">"ä¸ºæ­¤å¸æˆ·æä¾›ä¸€ä¸ªå称(å¯é€‰ï¼‰"</string>
- <string name="account_setup_names_user_name_label">"您的姓å(显示在å‘出的邮件中)"</string>
- <string name="account_setup_account_type_title">"添加新的电å­é‚®ä»¶å¸æˆ·"</string>
- <string name="account_setup_account_type_instructions">"è¿™æ˜¯ä»€ä¹ˆç±»åž‹çš„å¸æˆ·ï¼Ÿ"</string>
- <string name="account_setup_account_type_pop_action">"POP3 叿ˆ·"</string>
- <string name="account_setup_account_type_imap_action">"IMAP 叿ˆ·"</string>
- <string name="account_setup_incoming_title">"æ”¶ä»¶æœåŠ¡å™¨çš„è®¾ç½®"</string>
- <string name="account_setup_incoming_username_label">"用户å"</string>
- <string name="account_setup_incoming_password_label">"密ç "</string>
- <string name="account_setup_incoming_pop_server_label">"POP3 æœåС噍"</string>
- <string name="account_setup_incoming_imap_server_label">"IMAP æœåС噍"</string>
- <string name="account_setup_incoming_port_label">"端å£"</string>
- <string name="account_setup_incoming_security_label">"安全类型"</string>
- <string name="account_setup_incoming_security_none_label">"æ— "</string>
- <string name="account_setup_incoming_security_ssl_optional_label">"SSL(如果å¯ä»¥ä½¿ç”¨çš„è¯ï¼‰"</string>
- <string name="account_setup_incoming_security_ssl_label">"SSL(始终)"</string>
- <string name="account_setup_incoming_security_tls_optional_label">"TLS(如果å¯ä»¥ä½¿ç”¨çš„è¯ï¼‰"</string>
- <string name="account_setup_incoming_security_tls_label">"TLS(始终)"</string>
- <string name="account_setup_incoming_delete_policy_label">"从æœåŠ¡å™¨åˆ é™¤ç”µå­é‚®ä»¶"</string>
- <string name="account_setup_incoming_delete_policy_never_label">"从ä¸"</string>
- <string name="account_setup_incoming_delete_policy_7days_label">"7 天åŽ"</string>
- <string name="account_setup_incoming_delete_policy_delete_label">"从收件箱中删除邮件时"</string>
- <string name="account_setup_incoming_imap_path_prefix_label">"IMAP 路径å‰ç¼€"</string>
- <string name="account_setup_incoming_imap_path_prefix_hint">"å¯é€‰"</string>
- <string name="account_setup_outgoing_title">"外呿œåŠ¡å™¨è®¾ç½®"</string>
- <string name="account_setup_outgoing_smtp_server_label">"SMTP æœåС噍"</string>
- <string name="account_setup_outgoing_port_label">"端å£"</string>
- <string name="account_setup_outgoing_security_label">"安全类型"</string>
- <string name="account_setup_outgoing_require_login_label">"需è¦ç™»å½•。"</string>
- <string name="account_setup_outgoing_username_label">"用户å"</string>
- <string name="account_setup_outgoing_password_label">"密ç "</string>
- <string name="account_setup_options_title">"叿ˆ·é€‰é¡¹"</string>
- <string name="account_setup_options_mail_check_frequency_label">"电å­é‚®ä»¶æŸ¥æ”¶é¢‘率"</string>
- <string name="account_setup_options_mail_check_frequency_never">"从ä¸"</string>
- <string name="account_setup_options_mail_check_frequency_5min">"æ¯éš” 5 分钟"</string>
- <string name="account_setup_options_mail_check_frequency_10min">"æ¯éš” 10 分钟"</string>
- <string name="account_setup_options_mail_check_frequency_15min">"æ¯éš” 15 分钟"</string>
- <string name="account_setup_options_mail_check_frequency_30min">"æ¯éš” 30 分钟"</string>
- <string name="account_setup_options_mail_check_frequency_1hour">"æ¯éš”䏀尿—¶"</string>
- <string name="account_setup_options_default_label">"é»˜è®¤æƒ…å†µä¸‹ä»Žè¯¥å¸æˆ·å‘é€ç”µå­é‚®ä»¶ã€‚"</string>
- <string name="account_setup_options_notify_label">"收到电å­é‚®ä»¶æ—¶é€šçŸ¥æˆ‘。"</string>
- <string name="account_setup_failed_dlg_title">"无法完æˆè®¾ç½®"</string>
- <string name="account_setup_failed_dlg_auth_message">"ç”¨æˆ·åæˆ–密ç ä¸æ­£ç¡®ã€‚"</string>
- <string name="account_setup_failed_dlg_auth_message_fmt">"ç”¨æˆ·åæˆ–密ç ä¸æ­£ç¡®ã€‚"\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_certificate_message">"无法安全地连接到æœåŠ¡å™¨ã€‚"</string>
- <string name="account_setup_failed_dlg_certificate_message_fmt">"无法安全地连接到æœåŠ¡å™¨ã€‚"\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_server_message">"无法连接到æœåŠ¡å™¨ã€‚"</string>
- <string name="account_setup_failed_dlg_server_message_fmt">"无法连接到æœåŠ¡å™¨ã€‚"\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_tls_required">"必须使用 TLS,但æœåС噍䏿”¯æŒå®ƒã€‚"</string>
- <string name="account_setup_failed_auth_required">"èº«ä»½éªŒè¯æ–¹æ³•ä¸å—æœåŠ¡å™¨æ”¯æŒã€‚"</string>
- <string name="account_setup_failed_security">"出现安全错误,导致无法与æœåŠ¡å™¨å»ºç«‹è¿žæŽ¥ã€‚"</string>
- <string name="account_setup_failed_ioerror">"无法与æœåŠ¡å™¨å»ºç«‹è¿žæŽ¥ã€‚"</string>
- <string name="account_setup_failed_dlg_edit_details_action">"编辑详细信æ¯"</string>
- <string name="account_settings_title_fmt">"常规设置"</string>
- <string name="account_settings_default_label">"é»˜è®¤å¸æˆ·"</string>
- <string name="account_settings_default_summary">"é»˜è®¤æƒ…å†µä¸‹ä»Žè¯¥å¸æˆ·å‘é€ç”µå­é‚®ä»¶"</string>
- <string name="account_settings_notify_label">"电å­é‚®ä»¶é€šçŸ¥"</string>
- <string name="account_settings_notify_summary">"收到电å­é‚®ä»¶æ—¶åœ¨çŠ¶æ€æ ä¸­æ˜¾ç¤ºé€šçŸ¥"</string>
- <string name="account_settings_mail_check_frequency_label">"电å­é‚®ä»¶æŸ¥æ”¶é¢‘率"</string>
- <string name="account_settings_incoming_label">"接收设置"</string>
- <string name="account_settings_outgoing_label">"外å‘设置"</string>
- <string name="account_settings_add_account_label">"æ·»åŠ å…¶ä»–å¸æˆ·"</string>
- <string name="account_settings_description_label">"叿ˆ·åç§°"</string>
- <string name="account_settings_name_label">"您的姓å"</string>
- <string name="account_settings_notifications">"通知设置"</string>
- <string name="account_settings_vibrate_enable">"振动"</string>
- <string name="account_settings_vibrate_summary">"收到电å­é‚®ä»¶æ—¶å‘出振动"</string>
- <string name="account_settings_ringtone">"选择铃声"</string>
- <string name="account_settings_servers">"æœåŠ¡å™¨è®¾ç½®"</string>
- <string name="account_delete_dlg_title">"åˆ é™¤å¸æˆ·"</string>
- <string name="account_delete_dlg_instructions_fmt">"叿ˆ·â€œ<xliff:g id="ACCOUNT">%s</xliff:g>â€å°†ä»Žç”µå­é‚®ä»¶ä¸­åˆ é™¤ã€‚"</string>
- <string name="provider_note_yahoo">"æŸäº›ç±»åž‹çš„ Yahoo! 邮件叿ˆ·ä¸æ”¯æŒé‚®ç®±è®¿é—®ã€‚如果您在连接时é‡åˆ°é—®é¢˜ï¼Œè¯·è®¿é—® yahoo.com 了解更多信æ¯ã€‚"</string>
- <string name="provider_note_yahoo_uk">"在设置此电å­é‚®ä»¶å¸æˆ·ä¹‹å‰ï¼Œè¯·è®¿é—® Yahoo! ç½‘ç«™ï¼Œå¹¶ä¸ºæ­¤å¸æˆ·å¯ç”¨ POP3 电å­é‚®ä»¶æœåŠ¡ã€‚"</string>
- <string name="provider_note_live">"åªæœ‰éƒ¨åˆ†â€œå¢žå¼ºç‰ˆâ€å¸æˆ·èƒ½ä½¿ç”¨ POP,å¯è®©æ­¤ç¨‹åºè¿›è¡Œè¿žæŽ¥ã€‚如果您使用正确的电å­é‚®ä»¶åœ°å€å’Œå¯†ç ä¹Ÿæ— æ³•登录,则å¯èƒ½æ˜¯å› ä¸ºæ‚¨æ²¡æœ‰ä»˜è´¹çš„“增强版â€å¸æˆ·ã€‚请å¯åŠ¨ç½‘ç»œæµè§ˆå™¨ä»¥èŽ·å–æ­¤ç±»é‚®ä»¶å¸æˆ·ã€‚"</string>
- <string name="provider_note_t_online">"在设置此电å­é‚®ä»¶å¸æˆ·ä¹‹å‰ï¼Œè¯·è®¿é—® T-Online 网站,并创建密ç ä»¥ä¾¿é€šè¿‡ POP3 使用邮件æœåŠ¡ã€‚"</string>
-</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
deleted file mode 100644
index 5a650c357..000000000
--- a/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="read_attachment_label">"讀å–é›»å­éƒµä»¶é™„ä»¶"</string>
- <string name="read_attachment_desc">"å…許此應用程å¼è®€å–您的電å­éƒµä»¶é™„件。"</string>
- <string name="app_name">"é›»å­éƒµä»¶"</string>
- <string name="accounts_title">"您的帳戶"</string>
- <string name="compose_title">"撰寫郵件"</string>
- <string name="debug_title">"åµéŒ¯"</string>
- <string name="next_action">"下一步"</string>
- <string name="okay_action">"確定"</string>
- <string name="cancel_action">"å–æ¶ˆ"</string>
- <string name="send_action">"傳é€"</string>
- <string name="reply_action">"回覆"</string>
- <string name="reply_all_action">"全部回覆"</string>
- <string name="delete_action">"刪除"</string>
- <string name="forward_action">"轉寄"</string>
- <string name="done_action">"完æˆ"</string>
- <string name="discard_action">"æ¨æ£„"</string>
- <string name="save_draft_action">"儲存為è‰ç¨¿"</string>
- <string name="refresh_action">"釿–°æ•´ç†"</string>
- <string name="add_account_action">"新增帳戶"</string>
- <string name="compose_action">"撰寫郵件"</string>
- <string name="search_action">"æœå°‹"</string>
- <string name="open_action">"開啟"</string>
- <string name="account_settings_action">"帳戶設定"</string>
- <string name="remove_account_action">"移除帳戶"</string>
- <string name="accounts_action">"帳戶"</string>
- <string name="mark_as_read_action">"標示為已讀å–"</string>
- <string name="mark_as_unread_action">"標示為未讀å–"</string>
- <string name="add_cc_bcc_action">"新增副本/密件副本"</string>
- <string name="add_attachment_action">"新增附件"</string>
- <string name="dump_settings_action">"傾å°è¨­å®š"</string>
- <string name="accounts_context_menu_title">"帳戶é¸é …"</string>
- <string name="status_loading_more">"正在載入郵件..."</string>
- <string name="status_network_error">"連線錯誤"</string>
- <string name="status_loading_more_failed">"釿–°è¼‰å…¥æ›´å¤šéƒµä»¶"</string>
- <string name="notification_new_title">"æ–°é›»å­éƒµä»¶"</string>
- <string name="notification_new_one_account_fmt">"<xliff:g id="UNREAD_MESSAGE_COUNT">%d</xliff:g> å°æœªè®€å–的郵件 (<xliff:g id="ACCOUNT">%s</xliff:g>)"</string>
- <string name="notification_new_multi_account_fmt">"在 <xliff:g id="NUMBER_ACCOUNTS">%d</xliff:g> 個帳戶中"</string>
- <string name="special_mailbox_name_inbox">"收件匣"</string>
- <string name="accounts_welcome">"歡迎使用 [é›»å­éƒµä»¶] 設定ï¼"\n\n"[é›»å­éƒµä»¶] 設定å¯è®“您使用å„種電å­éƒµä»¶å¸³æˆ¶ï¼"\n\n"大部分常見的電å­éƒµä»¶åªéœ€è¦å…©å€‹æ­¥é©Ÿå°±èƒ½è¨­å®šå®Œæˆï¼"</string>
- <string name="debug_version_fmt">"版本:<xliff:g id="VERSION">%s</xliff:g>"</string>
- <string name="debug_enable_debug_logging_label">"è¦å•Ÿç”¨é™„加的åµéŒ¯è¨˜éŒ„嗎?"</string>
- <string name="debug_enable_sensitive_logging_label">"è¦å•Ÿç”¨æ•感資訊åµéŒ¯è¨˜éŒ„å—Ž (該記錄中å¯èƒ½æœƒé¡¯ç¤ºå¯†ç¢¼)?"</string>
- <string name="message_list_load_more_messages_action">"載入更多郵件"</string>
- <string name="message_compose_to_hint">"收件者"</string>
- <string name="message_compose_cc_hint">"副本"</string>
- <string name="message_compose_bcc_hint">"密件副本"</string>
- <string name="message_compose_subject_hint">"主旨"</string>
- <string name="message_compose_fwd_header_fmt">\n\n"--------原始郵件 --------"\n"主旨:<xliff:g id="SUBJECT">%s</xliff:g>"\n"寄件者:<xliff:g id="SENDER">%s</xliff:g>"\n"收件者:<xliff:g id="TO">%s</xliff:g>"\n"副本:<xliff:g id="CC_0">%s</xliff:g>"\n\n</string>
- <string name="message_compose_reply_header_fmt">\n\n"<xliff:g id="SENDER">%s</xliff:g>æåˆ°ï¼š"\n\n</string>
- <string name="message_compose_quoted_text_label">"引用的文字"</string>
- <string name="message_compose_error_no_recipients">"æ‚¨å¿…é ˆæ–°å¢žè‡³å°‘ä¸€ä½æ”¶ä»¶è€…。"</string>
- <string name="message_compose_attachments_skipped_toast">"尚未下載部分附件,因此無法予以轉寄。"</string>
- <string name="message_view_to_label">"收件者:"</string>
- <string name="message_view_cc_label">"副本:"</string>
- <string name="message_view_attachment_view_action">"開啟"</string>
- <string name="message_view_attachment_download_action">"儲存"</string>
- <string name="message_view_prev_action">"上一å°éƒµä»¶"</string>
- <string name="message_view_next_action">"下一å°éƒµä»¶"</string>
- <string name="message_view_status_attachment_saved">"已將附件儲存至 SD 記憶å¡ï¼Œæª”å為 <xliff:g id="FILENAME">%s</xliff:g>。"</string>
- <string name="message_view_status_attachment_not_saved">"無法將附件儲存至 SD 記憶å¡ã€‚"</string>
- <string name="message_view_show_pictures_instructions">"é¸å– [顯示圖片] å³å¯é¡¯ç¤ºå…§åµŒçš„圖片。"</string>
- <string name="message_view_show_pictures_action">"顯示圖片"</string>
- <string name="message_view_fetching_attachment_toast">"正在å–得附件。"</string>
- <string name="message_deleted_toast">"已刪除郵件。"</string>
- <string name="message_discarded_toast">"å·²æ¨æ£„郵件。"</string>
- <string name="message_saved_toast">"已儲存郵件è‰ç¨¿ã€‚"</string>
- <string name="account_setup_basics_title">"設定電å­éƒµä»¶"</string>
- <string name="account_setup_basics_instructions">"請輸入您帳戶的電å­éƒµä»¶åœ°å€ï¼š"</string>
- <string name="account_setup_basics_email_hint">"é›»å­éƒµä»¶åœ°å€"</string>
- <string name="account_setup_basics_password_hint">"密碼"</string>
- <string name="account_setup_basics_default_label">"é è¨­ä½¿ç”¨é€™å€‹å¸³æˆ¶å‚³é€é›»å­éƒµä»¶ã€‚"</string>
- <string name="account_setup_basics_manual_setup_action">"手動設定"</string>
- <string name="account_setup_username_password_toast">"請輸入有效的電å­éƒµä»¶åœ°å€å’Œå¯†ç¢¼ã€‚"</string>
- <string name="account_setup_check_settings_retr_info_msg">"正在擷å–帳戶資訊..."</string>
- <string name="account_setup_check_settings_check_incoming_msg">"正在檢查內收伺æœå™¨è¨­å®š..."</string>
- <string name="account_setup_check_settings_check_outgoing_msg">"正在檢查外寄伺æœå™¨è¨­å®š..."</string>
- <string name="account_setup_check_settings_canceling_msg">"å–æ¶ˆä¸­..."</string>
- <string name="account_setup_names_title">"設定電å­éƒµä»¶"</string>
- <string name="account_setup_names_instructions">"帳戶已設定完æˆï¼Œæ‚¨å¯ä»¥æ”¶ç™¼é›»å­éƒµä»¶äº†ï¼"</string>
- <string name="account_setup_names_account_name_label">"為此帳戶命å (é¸ç”¨)"</string>
- <string name="account_setup_names_user_name_label">"您的å稱 (顯示於外寄郵件)"</string>
- <string name="account_setup_account_type_title">"新增電å­éƒµä»¶å¸³æˆ¶"</string>
- <string name="account_setup_account_type_instructions">"帳戶類型為何?"</string>
- <string name="account_setup_account_type_pop_action">"POP3 帳戶"</string>
- <string name="account_setup_account_type_imap_action">"IMAP 帳戶"</string>
- <string name="account_setup_incoming_title">"內收伺æœå™¨è¨­å®š"</string>
- <string name="account_setup_incoming_username_label">"使用者å稱"</string>
- <string name="account_setup_incoming_password_label">"密碼"</string>
- <string name="account_setup_incoming_pop_server_label">"POP3 伺æœå™¨"</string>
- <string name="account_setup_incoming_imap_server_label">"IMAP 伺æœå™¨"</string>
- <string name="account_setup_incoming_port_label">"通訊埠"</string>
- <string name="account_setup_incoming_security_label">"安全性類型"</string>
- <string name="account_setup_incoming_security_none_label">"ç„¡"</string>
- <string name="account_setup_incoming_security_ssl_optional_label">"SSL (如果å¯ç”¨)"</string>
- <string name="account_setup_incoming_security_ssl_label">"SSL (æ°¸é å•Ÿç”¨)"</string>
- <string name="account_setup_incoming_security_tls_optional_label">"TLS (如果å¯ç”¨)"</string>
- <string name="account_setup_incoming_security_tls_label">"TLS (æ°¸é )"</string>
- <string name="account_setup_incoming_delete_policy_label">"從伺æœå™¨ä¸­åˆªé™¤é›»å­éƒµä»¶"</string>
- <string name="account_setup_incoming_delete_policy_never_label">"æ°¸ä¸åˆªé™¤"</string>
- <string name="account_setup_incoming_delete_policy_7days_label">"7 天後刪除"</string>
- <string name="account_setup_incoming_delete_policy_delete_label">"當我從收件匣刪除時"</string>
- <string name="account_setup_incoming_imap_path_prefix_label">"IMAP 路徑字首"</string>
- <string name="account_setup_incoming_imap_path_prefix_hint">"é¸ç”¨"</string>
- <string name="account_setup_outgoing_title">"外寄伺æœå™¨è¨­å®š"</string>
- <string name="account_setup_outgoing_smtp_server_label">"SMTP 伺æœå™¨"</string>
- <string name="account_setup_outgoing_port_label">"通訊埠"</string>
- <string name="account_setup_outgoing_security_label">"安全性類型"</string>
- <string name="account_setup_outgoing_require_login_label">"必須登入。"</string>
- <string name="account_setup_outgoing_username_label">"使用者å稱"</string>
- <string name="account_setup_outgoing_password_label">"密碼"</string>
- <string name="account_setup_options_title">"帳戶é¸é …"</string>
- <string name="account_setup_options_mail_check_frequency_label">"檢查電å­éƒµä»¶çš„頻率"</string>
- <string name="account_setup_options_mail_check_frequency_never">"ä¸è¦æª¢æŸ¥"</string>
- <string name="account_setup_options_mail_check_frequency_5min">"æ¯ 5 åˆ†é˜æª¢æŸ¥ä¸€æ¬¡"</string>
- <string name="account_setup_options_mail_check_frequency_10min">"æ¯ 10 åˆ†é˜æª¢æŸ¥ä¸€æ¬¡"</string>
- <string name="account_setup_options_mail_check_frequency_15min">"æ¯ 15 åˆ†é˜æª¢æŸ¥ä¸€æ¬¡"</string>
- <string name="account_setup_options_mail_check_frequency_30min">"æ¯ 30 åˆ†é˜æª¢æŸ¥ä¸€æ¬¡"</string>
- <string name="account_setup_options_mail_check_frequency_1hour">"æ¯å°æ™‚檢查一次"</string>
- <string name="account_setup_options_default_label">"é è¨­ä½¿ç”¨é€™å€‹å¸³æˆ¶å‚³é€é›»å­éƒµä»¶ã€‚"</string>
- <string name="account_setup_options_notify_label">"收到電å­éƒµä»¶æ™‚通知我。"</string>
- <string name="account_setup_failed_dlg_title">"無法完æˆè¨­å®š"</string>
- <string name="account_setup_failed_dlg_auth_message">"使用者åç¨±æˆ–å¯†ç¢¼ä¸æ­£ç¢ºã€‚"</string>
- <string name="account_setup_failed_dlg_auth_message_fmt">"使用者åç¨±æˆ–å¯†ç¢¼ä¸æ­£ç¢ºã€‚"\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_certificate_message">"無法安全地連線至伺æœå™¨ã€‚"</string>
- <string name="account_setup_failed_dlg_certificate_message_fmt">"無法安全地連線至伺æœå™¨ã€‚"\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_dlg_server_message">"無法連線至伺æœå™¨ã€‚"</string>
- <string name="account_setup_failed_dlg_server_message_fmt">"無法連線至伺æœå™¨ã€‚"\n"(<xliff:g id="ERROR">%s</xliff:g>)"</string>
- <string name="account_setup_failed_tls_required">"必須使用 TLS,但此伺æœå™¨ä¸æ”¯æ´ã€‚"</string>
- <string name="account_setup_failed_auth_required">"伺æœå™¨ä¸æ”¯æ´é€™äº›é©—證方法。"</string>
- <string name="account_setup_failed_security">"發生安全性錯誤,無法連線至伺æœå™¨ã€‚"</string>
- <string name="account_setup_failed_ioerror">"無法連線至伺æœå™¨ã€‚"</string>
- <string name="account_setup_failed_dlg_edit_details_action">"編輯詳細資訊"</string>
- <string name="account_settings_title_fmt">"一般設定"</string>
- <string name="account_settings_default_label">"é è¨­å¸³æˆ¶"</string>
- <string name="account_settings_default_summary">"é è¨­ä½¿ç”¨é€™å€‹å¸³æˆ¶å‚³é€é›»å­éƒµä»¶"</string>
- <string name="account_settings_notify_label">"é›»å­éƒµä»¶é€šçŸ¥"</string>
- <string name="account_settings_notify_summary">"收到電å­éƒµä»¶æ™‚,在狀態列中顯示通知"</string>
- <string name="account_settings_mail_check_frequency_label">"檢查電å­éƒµä»¶çš„頻率"</string>
- <string name="account_settings_incoming_label">"內收設定"</string>
- <string name="account_settings_outgoing_label">"外寄設定"</string>
- <string name="account_settings_add_account_label">"新增其他帳戶"</string>
- <string name="account_settings_description_label">"帳戶å稱"</string>
- <string name="account_settings_name_label">"您的å稱"</string>
- <string name="account_settings_notifications">"通知設定"</string>
- <string name="account_settings_vibrate_enable">"振動"</string>
- <string name="account_settings_vibrate_summary">"收到電å­éƒµä»¶æ™‚也振動"</string>
- <string name="account_settings_ringtone">"é¸å–鈴è²"</string>
- <string name="account_settings_servers">"伺æœå™¨è¨­å®š"</string>
- <string name="account_delete_dlg_title">"移除帳戶"</string>
- <string name="account_delete_dlg_instructions_fmt">"系統將從 [é›»å­éƒµä»¶] 中移除帳戶「<xliff:g id="ACCOUNT">%s</xliff:g>ã€ã€‚"</string>
- <string name="provider_note_yahoo">"䏿”¯æ´æŸäº›é¡žåž‹çš„ Yahoo! 郵件帳戶信箱。如果您無法順利連線,請造訪 yahoo.com 以å–得詳細資訊。"</string>
- <string name="provider_note_yahoo_uk">"在設定此電å­éƒµä»¶å¸³æˆ¶å‰ï¼Œè«‹å…ˆé€ è¨ª Yahoo! 網站,並啟用這個帳戶的 POP3 é›»å­éƒµä»¶æ”¶ç™¼åŠŸèƒ½ã€‚"</string>
- <string name="provider_note_live">"åªæœ‰éƒ¨åˆ†åŒ…å« POP å­˜å–功能的「Plusã€å¸³æˆ¶èƒ½èˆ‡é€™å€‹ç¨‹å¼é€£ç·šã€‚如果您輸入的電å­éƒµä»¶åœ°å€å’Œå¯†ç¢¼ç„¡èª¤ï¼Œå»ä»ç„¡æ³•登入,表示您å¯èƒ½å°šæœªè³¼è²·ã€ŒPlusã€å¸³æˆ¶ã€‚請啟動網é ç€è¦½å™¨ï¼Œä»¥å­˜å–這些電å­éƒµä»¶å¸³æˆ¶ã€‚"</string>
- <string name="provider_note_t_online">"在設定此電å­éƒµä»¶å¸³æˆ¶å‰ï¼Œè«‹å…ˆé€ è¨ª T-Online 網站,並設定 POP3 é›»å­éƒµä»¶æ”¶ç™¼åŠŸèƒ½çš„å¯†ç¢¼ã€‚"</string>
-</resources>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
deleted file mode 100644
index cdf14b159..000000000
--- a/res/values/arrays.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<resources>
-
- <!-- Do not change any of the values in this array without checking/changing -->
- <!-- related values in: AccountSetupBasics.java & AccountSetupOptions.java -->
-
- <!-- In particular, 15 minutes is hardcoded as the default for new accounts. -->
-
- <string-array name="account_settings_check_frequency_entries">
- <item>@string/account_setup_options_mail_check_frequency_never</item>
- <item>@string/account_setup_options_mail_check_frequency_5min</item>
- <item>@string/account_setup_options_mail_check_frequency_10min</item>
- <item>@string/account_setup_options_mail_check_frequency_15min</item>
- <item>@string/account_setup_options_mail_check_frequency_30min</item>
- <item>@string/account_setup_options_mail_check_frequency_1hour</item>
- </string-array>
-
- <string-array name="account_settings_check_frequency_values" translatable="false">
- <item>-1</item>
- <item>5</item>
- <item>10</item>
- <item>15</item>
- <item>30</item>
- <item>60</item>
- </string-array>
-
-</resources>
diff --git a/res/values/build_number.xml b/res/values/build_number.xml
deleted file mode 100644
index 9c414d2a2..000000000
--- a/res/values/build_number.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<resources>
- <string name="build_number" translatable="false">20080722-0001</string>
-</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
deleted file mode 100644
index 897f0b53c..000000000
--- a/res/values/colors.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<resources>
- <color name="folder_message_list_child_background">#3B3B3B</color>
-</resources> \ No newline at end of file
diff --git a/res/values/dimensions.xml b/res/values/dimensions.xml
deleted file mode 100644
index 5951409b0..000000000
--- a/res/values/dimensions.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<resources>
- <dimen name="button_minWidth">100sp</dimen>
-</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
deleted file mode 100644
index d57727d11..000000000
--- a/res/values/strings.xml
+++ /dev/null
@@ -1,366 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- Permissions label -->
- <string name="read_attachment_label">read Email attachments</string>
- <!-- Permissions description -->
- <string name="read_attachment_desc">Allows this application to read your Email attachments.</string>
- <!-- Name of application on Home screen -->
- <string name="app_name">Email</string>
- <!-- Title of Accounts screen -->
- <string name="accounts_title">Your accounts</string>
- <!-- Title of compose screen -->
- <string name="compose_title">Compose</string>
- <!-- Title of debug screen -->
- <string name="debug_title">Debug</string>
-
- <!-- Actions will be used as buttons and in menu items -->
- <skip />
-
- <!-- Used as part of a multi-step process -->
- <string name="next_action">Next</string>
- <!-- Button name used to confirm acceptance of dialog boxes, warnings, errors, etc. -->
- <string name="okay_action">OK</string>
- <!-- Button name used to cancel out of dialog boxes -->
- <string name="cancel_action">Cancel</string>
- <!-- Menu item/button name -->
- <string name="send_action">Send</string>
- <!-- Menu item/button name -->
- <string name="reply_action">Reply</string>
- <!-- Menu item/button name -->
- <string name="reply_all_action">Reply all</string>
- <!-- Menu item/button name -->
- <string name="delete_action">Delete</string>
- <!-- Menu item/button name -->
- <string name="forward_action">Forward</string>
- <!-- Button name used to complete a multi-step process -->
- <string name="done_action">Done</string>
- <!-- Menu item/button name -->
- <string name="discard_action">Discard</string>
- <!-- Menu item/button name -->
- <string name="save_draft_action">Save as draft</string>
- <!-- Menu item -->
- <string name="refresh_action">Refresh</string>
- <!-- Menu item -->
- <string name="add_account_action">Add account</string>
- <!-- Menu item -->
- <string name="compose_action">Compose</string>
- <!-- Menu item/button name -->
- <string name="search_action">Search</string>
- <!-- Menu item/button name -->
- <string name="open_action">Open</string>
- <!-- Menu item -->
- <string name="account_settings_action">Account settings</string>
- <!-- Menu item -->
- <string name="remove_account_action">Remove account</string>
- <!-- Menu item -->
- <string name="accounts_action">Accounts</string>
- <!-- Menu item -->
- <string name="mark_as_read_action">Mark as read</string>
- <!-- Menu item -->
- <string name="mark_as_unread_action">Mark as unread</string>
- <!-- Menu item -->
- <string name="add_cc_bcc_action">Add Cc/Bcc</string>
- <!-- Menu item -->
- <string name="add_attachment_action">Add attachment</string>
- <!-- Menu item (debug screen) -->
- <string name="dump_settings_action">Dump settings</string>
- <!-- Title of account context menu -->
- <string name="accounts_context_menu_title">Account options</string>
- <!-- Appears in message list view while messages are being loaded -->
- <string name="status_loading_more">Loading messages\u2026</string>
- <!-- Appears in message list view when there's a network error. -->
- <!-- Also appears in a toast, in the message viewer, when there's a network error. -->
- <string name="status_network_error">Connection error</string>
- <!-- Appears in message list view when error when trying to "Load more messages". -->
- <string name="status_loading_more_failed">Retry loading more messages</string>
- <!-- Notification title in status bar -->
- <string name="notification_new_title">New email</string>
- <!-- Notification message in notifications window and one account has new mail; e.g, "279 unread (someone@google.com)" -->
- <string name="notification_new_one_account_fmt"><xliff:g id="unread_message_count">%d</xliff:g> unread (<xliff:g id="account">%s</xliff:g>)</string>
- <!-- Notification message in notifications window and 2+ accounts has new mail; e.g, "in 3 accounts" -->
- <string name="notification_new_multi_account_fmt">in <xliff:g id="number_accounts">%d</xliff:g> accounts</string>
-
- <!-- In the folder list view, the inbox will be displayed with this name -->
- <string name="special_mailbox_name_inbox">Inbox</string>
- <!-- Do Not Translate. This is the name of the "outbox" folder, on the server. -->
- <string name="special_mailbox_name_outbox">Outbox</string>
- <!-- Do Not Translate. This is the name of the "drafts" folder, on the server. -->
- <string name="special_mailbox_name_drafts">Drafts</string>
- <!-- Do Not Translate. This is the name of the "trash" folder, on the server. -->
- <string name="special_mailbox_name_trash">Trash</string>
- <!-- Do Not Translate. This is the name of the "sent" folder, on the server. -->
- <string name="special_mailbox_name_sent">Sent</string>
- <!-- Text on screen when you don't have any external email accounts set up -->
- <string name="accounts_welcome">Welcome to Email setup!\n\nUse any email account with Email.\n\nMost popular email accounts can be set up in 2 steps!</string>
-
- <!-- Version number, shown only on debug screen -->
- <string name="debug_version_fmt">Version: <xliff:g id="version">%s</xliff:g></string>
- <!-- Checkbox label, shown only on debug screen -->
- <string name="debug_enable_debug_logging_label">Enable extra debug logging?</string>
- <!-- Checkbox label, shown only on debug screen -->
- <string name="debug_enable_sensitive_logging_label">Enable sensitive information debug logging? (May show passwords in logs.)</string>
-
- <!-- Appears at the bottom of list of messages; user selects to load more messages from that folder. -->
- <string name="message_list_load_more_messages_action">Load more messages</string>
- <!-- Hint text in To field -->
- <string name="message_compose_to_hint">To</string>
- <!-- Hint text in Cc field -->
- <string name="message_compose_cc_hint">Cc</string>
- <!-- Hint text in Bcc field -->
- <string name="message_compose_bcc_hint">Bcc</string>
- <!-- Hint text in Subject field -->
- <string name="message_compose_subject_hint">Subject</string>
- <!-- Header for forwarded original messages -->
- <string name="message_compose_fwd_header_fmt">\n\n-------- Original Message --------\nSubject: <xliff:g id="subject">%s</xliff:g>\nFrom: <xliff:g id="sender">%s</xliff:g>\nTo: <xliff:g id="to">%s</xliff:g>\nCC: <xliff:g id="cc">%s</xliff:g>\n\n</string>
- <!-- Header for replied-to messages -->
- <string name="message_compose_reply_header_fmt">\n\n<xliff:g id="sender">%s</xliff:g> wrote:\n\n</string>
- <!-- Heading that appears before forwarded text -->
- <string name="message_compose_quoted_text_label">Quoted text</string>
- <!-- Toast that appears if you try to send with no recipients. -->
- <string name="message_compose_error_no_recipients">You must add at least one recipient.</string>
- <!-- Toast that appears in the context of forwarding a message with attachment(s) -->
- <string name="message_compose_attachments_skipped_toast">Some attachments cannot be forwarded because they have not downloaded.</string>
- <!-- Label for To field in read message view -->
- <string name="message_view_to_label">To:</string>
- <!-- Label for CC field in read message view -->
- <string name="message_view_cc_label">Cc:</string>
- <!-- Menu item -->
- <string name="message_view_attachment_view_action">Open</string>
- <!-- Button name -->
- <string name="message_view_attachment_download_action">Save</string>
- <!-- Button name on read email screen -->
- <string name="message_view_prev_action">Prev message</string>
- <!-- Button name on read email screen -->
- <string name="message_view_next_action">Next message</string>
- <!-- Toast after saving attachment -->
- <string name="message_view_status_attachment_saved">Attachment saved to SD card as <xliff:g id="filename">%s</xliff:g>.</string>
- <!-- Toast after attachment could not be saved-->
- <string name="message_view_status_attachment_not_saved">Unable to save attachment to SD card.</string>
- <!-- Displayed in message view -->
- <string name="message_view_show_pictures_instructions">Select \"Show pictures\" to display embedded pictures.</string>
- <!-- Button on email opened for reading -->
- <string name="message_view_show_pictures_action">Show pictures</string>
- <!-- Toast while fetching attachment -->
- <string name="message_view_fetching_attachment_toast">Fetching attachment.</string>
- <!-- Toast shown briefly while deleting a message -->
- <string name="message_deleted_toast">Message deleted.</string>
- <!-- Toast shown briefly while deleting an unsent (draft) message -->
- <string name="message_discarded_toast">Message discarded.</string>
- <!-- Toast shown briefly while saving a draft -->
- <string name="message_saved_toast">Message saved as draft.</string>
- <!-- Title of screen when setting up new email account -->
- <string name="account_setup_basics_title">Set up email</string>
- <!-- On "Set up email" screen, brief instructions -->
- <string name="account_setup_basics_instructions">Type your account email address:</string>
- <!-- On "Set up email" screen, hint for account email address text field -->
- <string name="account_setup_basics_email_hint">Email address</string>
- <!-- On "Set up email" screen, hint for account email password text field -->
- <string name="account_setup_basics_password_hint">Password</string>
- <!-- On "Set up email" screen, checkbox label for making this the new account be the default account -->
- <string name="account_setup_basics_default_label">Send email from this account by default.</string>
- <!-- Button name on "Set up email" screen -->
- <string name="account_setup_basics_manual_setup_action">Manual setup</string>
- <!-- Toast when we can't build a URI from the given email & password -->
- <!-- Note, the error message in the toast is purposefully vague, because I *don't* know exactly what's wrong. -->
- <string name="account_setup_username_password_toast">Please type a valid email address and password.</string>
-
- <!-- Do Not Translate. Activity Title for check-settings screen -->
- <string name="account_setup_check_settings_title"></string>
- <!-- On check-settings screen, this is the initially-displayed message. -->
- <string name="account_setup_check_settings_retr_info_msg">Retrieving account information\u2026</string>
- <!-- Appears on screen while system is checking incoming server settings -->
- <string name="account_setup_check_settings_check_incoming_msg">Checking incoming server settings\u2026</string>
- <!-- Appears on screen while system is checking outgoing server settings -->
- <string name="account_setup_check_settings_check_outgoing_msg">Checking outgoing server settings\u2026</string>
- <!-- On check-settings screen, displayed briefly when user cancels the operation. -->
- <string name="account_setup_check_settings_canceling_msg">Canceling\u2026</string>
- <!-- Title of "Set up email" screen after success -->
- <string name="account_setup_names_title">Set up email</string>
- <!-- Text that appears on top of "Set up email" screen after successfully setting up an account -->
- <string name="account_setup_names_instructions">Your account is set up, and email is on its way!</string>
- <!-- On "Set up email" screen, label of text field -->
- <string name="account_setup_names_account_name_label">Give this account a name (optional)</string>
- <!-- On "Set up email" screen, label of text field -->
- <string name="account_setup_names_user_name_label">Your name (displayed on outgoing messages)</string>
-
- <!-- Activity Title for the first screen in manual setup (where you select IMAP or POP3) -->
- <string name="account_setup_account_type_title">Add new email account</string>
- <!-- "Add new email account" screen, text that appears on screen -->
- <string name="account_setup_account_type_instructions">What type of account is this?</string>
- <!-- "Add new email account" screen, button name in response to what type of account this is -->
- <string name="account_setup_account_type_pop_action">POP3 account</string>
- <!-- "Add new email account" screen, button name in response to what type of account this is -->
- <string name="account_setup_account_type_imap_action">IMAP account</string>
- <!-- "Incoming server settings" screen, label for text field -->
- <string name="account_setup_incoming_title">Incoming server settings</string>
- <!-- "Incoming server settings" screen, label for text field -->
- <string name="account_setup_incoming_username_label">Username</string>
- <!-- "Incoming server settings" screen, label for text field -->
- <string name="account_setup_incoming_password_label">Password</string>
- <!-- "Incoming server settings" screen, label for text field -->
- <string name="account_setup_incoming_pop_server_label">POP3 server</string>
- <!-- "Incoming server settings" screen, label for text field -->
- <string name="account_setup_incoming_imap_server_label">IMAP server</string>
- <!-- "Incoming server settings" screen, label for text field -->
- <string name="account_setup_incoming_port_label">Port</string>
- <!-- "Incoming server settings" screen, label for pop-up menu -->
- <string name="account_setup_incoming_security_label">Security type</string>
- <!-- "Incoming server settings" screen, options for "Security type" pop-up menu -->
- <string name="account_setup_incoming_security_none_label">None</string>
- <!-- "Incoming server settings" screen, options for "Security type" pop-up menu -->
- <string name="account_setup_incoming_security_ssl_optional_label">SSL (if available)</string>
- <!-- "Incoming server settings" screen, options for "Security type" pop-up menu -->
- <string name="account_setup_incoming_security_ssl_label">SSL (always)</string>
- <!-- "Incoming server settings" screen, options for "Security type" pop-up menu -->
- <string name="account_setup_incoming_security_tls_optional_label">TLS (if available)</string>
- <!-- "Incoming server settings" screen, options for "Security type" pop-up menu -->
- <string name="account_setup_incoming_security_tls_label">TLS (always)</string>
- <!-- "Incoming server settings" screen, label for pop-up menu -->
- <string name="account_setup_incoming_delete_policy_label">Delete email from server</string>
- <!-- "Incoming server settings" screen, options in pop-up menu for Delete email from server: -->
- <!-- "Incoming server settings" screen, options in pop-up menu for Delete email from server: -->
- <string name="account_setup_incoming_delete_policy_never_label">Never</string>
- <!-- "Incoming server settings" screen, options in pop-up menu for Delete email from server: -->
- <string name="account_setup_incoming_delete_policy_7days_label">After 7 days</string>
- <!-- "Incoming server settings" screen, options in pop-up menu for Delete email from server: -->
- <string name="account_setup_incoming_delete_policy_delete_label">When I delete from Inbox</string>
-
- <!-- "Incoming server settings" screen, label for setting IMAP path prefix: -->
- <string name="account_setup_incoming_imap_path_prefix_label">IMAP path prefix</string>
- <!-- "Incoming server settings" screen, hint for setting IMAP path prefix: -->
- <string name="account_setup_incoming_imap_path_prefix_hint">Optional</string>
- <!-- Title of "Outgoing server settings" screen -->
- <string name="account_setup_outgoing_title">Outgoing server settings</string>
- <!-- On "Outgoing server settings" screen, label for text field -->
- <string name="account_setup_outgoing_smtp_server_label">SMTP server</string>
- <!-- On "Outgoing server settings" screen, label for text field -->
- <string name="account_setup_outgoing_port_label">Port</string>
- <!-- On "Outgoing server settings" screen, label for pop-up menu -->
- <string name="account_setup_outgoing_security_label">Security type</string>
- <!-- On "Outgoing server settings" screen, label for check box -->
- <string name="account_setup_outgoing_require_login_label">Require sign-in.</string>
- <!-- On "Outgoing server settings" screen, label for text field -->
- <string name="account_setup_outgoing_username_label">Username</string>
- <!-- On "Outgoing server settings" screen, label for text field -->
- <string name="account_setup_outgoing_password_label">Password</string>
-
- <!-- In Account setup options screen, Activity title -->
- <string name="account_setup_options_title">Account options</string>
- <!-- In Account setup options screen, label for email check frequency selector -->
- <string name="account_setup_options_mail_check_frequency_label">Email checking frequency</string>
- <!-- In Account setup options & Account Settings screens, label for email check frequency option -->
- <string name="account_setup_options_mail_check_frequency_never">Never</string>
- <!-- In Account setup options & Account Settings screens, email check frequency option -->
- <string name="account_setup_options_mail_check_frequency_5min">Every 5 minutes</string>
- <!-- In Account setup options & Account Settings screens, email check frequency option -->
- <string name="account_setup_options_mail_check_frequency_10min">Every 10 minutes</string>
- <!-- In Account setup options & Account Settings screens, email check frequency option -->
- <string name="account_setup_options_mail_check_frequency_15min">Every 15 minutes</string>
- <!-- In Account setup options & Account Settings screens, email check frequency option -->
- <string name="account_setup_options_mail_check_frequency_30min">Every 30 minutes</string>
- <!-- In Account setup options & Account Settings screens, email check frequency option -->
- <string name="account_setup_options_mail_check_frequency_1hour">Every hour</string>
- <!-- Check box label on "Set up email" screen to make this the default account -->
- <!-- Note, this should usually match the default account summary preference string -->
- <string name="account_setup_options_default_label">Send email from this account by default.</string>
- <!-- In Account setup options & Account Settings screens, check box for new-mail notification -->
- <string name="account_setup_options_notify_label">Notify me when email arrives.</string>
- <!-- Dialog title when "setup" could not finish -->
- <string name="account_setup_failed_dlg_title">Setup could not finish</string>
-
- <!-- "Setup could not finish" dialog text; e.g., Username or password incorrect -->
- <string name="account_setup_failed_dlg_auth_message">Username or password incorrect.</string>
- <!-- "Setup could not finish" dialog text; e.g., Username or password incorrect\n(ERR01 Account does not exist) -->
- <string name="account_setup_failed_dlg_auth_message_fmt">Username or password incorrect.\n(<xliff:g id="error">%s</xliff:g>)</string>
-
- <!-- "Setup could not finish" dialog text; e.g., Cannot safely connect to server -->
- <string name="account_setup_failed_dlg_certificate_message">Cannot safely connect to server.</string>
- <!-- "Setup could not finish" dialog text; e.g., Cannot safely connect to server\n(TLS Not Supported) -->
- <string name="account_setup_failed_dlg_certificate_message_fmt">Cannot safely connect to server.\n(<xliff:g id="error">%s</xliff:g>)</string>
-
- <!-- "Setup could not finish" dialog text; e.g., Cannot connect to server -->
- <string name="account_setup_failed_dlg_server_message">Cannot connect to server.</string>
- <!-- "Setup could not finish" dialog text; e.g., Cannot connect to server\n(Connection timed out) -->
- <string name="account_setup_failed_dlg_server_message_fmt">Cannot connect to server.\n(<xliff:g id="error">%s</xliff:g>)</string>
-
- <!-- Additional diagnostic text when TLS was required but the server doesn't support it -->
- <string name="account_setup_failed_tls_required">TLS required but not supported by server.</string>
- <!-- Additional diagnostic text when server does not support any of our authentication methods -->
- <string name="account_setup_failed_auth_required">Authentication methods are not supported by server.</string>
- <!-- Additional diagnostic text when server connection failed due to security error -->
- <string name="account_setup_failed_security">Unable to open connection to server due to security error.</string>
- <!-- Additional diagnostic text when server connection failed due to io error (connection) -->
- <string name="account_setup_failed_ioerror">Unable to open connection to server.</string>
-
- <!-- "Setup could not finish" dialog action button -->
- <string name="account_setup_failed_dlg_edit_details_action">Edit details</string>
- <!-- On Settings screen, section heading -->
- <string name="account_settings_title_fmt">General settings</string>
- <!-- On Settings screen, setting option name -->
- <string name="account_settings_default_label">Default account</string>
- <!-- Check box "summary" label on "Account options" screen to make this the default account -->
- <!-- Note, this should usually match the default account account setup checkbox string -->
- <string name="account_settings_default_summary">Send email from this account by default</string>
- <!-- On Settings screen, setting option name -->
- <string name="account_settings_notify_label">Email notifications</string>
- <!-- On Settings screen, setting summary text -->
- <string name="account_settings_notify_summary">Notify in status bar when email arrives</string>
- <!-- On Settings screen, setting option name and title of dialog box that opens -->
- <string name="account_settings_mail_check_frequency_label">Email check frequency</string>
- <!-- On Settings screen, setting option name -->
- <string name="account_settings_incoming_label">Incoming settings</string>
- <!-- On Settings screen, setting option name -->
- <string name="account_settings_outgoing_label">Outgoing settings</string>
- <!-- On Settings screen, setting option name -->
- <string name="account_settings_add_account_label">Add another account</string>
- <!-- On Settings screen, setting option name -->
- <string name="account_settings_description_label">Account name</string>
- <!-- On Settings screen, setting option name -->
- <string name="account_settings_name_label">Your name</string>
- <!-- On Settings screen, section heading -->
- <string name="account_settings_notifications">Notification settings</string>
- <!-- On Settings screen, setting check box label -->
- <string name="account_settings_vibrate_enable">Vibrate</string>
- <!-- On Settings screen, setting summary text -->
- <string name="account_settings_vibrate_summary">Also vibrate when email arrives</string>
- <!-- On Settings screen, setting option name -->
- <string name="account_settings_ringtone">Select ringtone</string>
- <!-- On Settings screen, section heading -->
- <string name="account_settings_servers">Server settings</string>
- <!-- Title of Remove account confirmation dialog box -->
- <string name="account_delete_dlg_title">Remove account</string>
- <!-- Message of Remove account confirmation dialog box -->
- <string name="account_delete_dlg_instructions_fmt">The account \"<xliff:g id="account">%s</xliff:g>\" will be removed from Email.</string>
-
- <!-- Message that appears when user adds a Yahoo mail account. This alert has no title. -->
- <string name="provider_note_yahoo">Mailbox access is not supported for some types of
- Yahoo! mail accounts. If you have trouble connecting, visit yahoo.com for more
- information.</string>
- <!-- Message that appears when user adds a Yahoo UK mail account. -->
- <string name="provider_note_yahoo_uk">Before setting up this email account, please visit the
- Yahoo! web site and enable POP3 email access for this account.</string>
- <!-- Message that appears when adding a Windows Live Hotmail Plus account -->
- <string name="provider_note_live">Only some \"Plus\" accounts include POP access
- allowing this program to connect. If you are not able to sign in with
- your correct email address and password, you may not have a paid
- \"Plus\" account. Please launch the Web browser to gain access to
- these mail accounts.</string>
- <!-- Message that appears when adding a T-Online account -->
- <string name="provider_note_t_online">Before setting up this email account, please visit the T-Online Web site and create a password for POP3 email access.</string>
-</resources>
diff --git a/res/xml/account_settings_preferences.xml b/res/xml/account_settings_preferences.xml
deleted file mode 100644
index a9f40f50f..000000000
--- a/res/xml/account_settings_preferences.xml
+++ /dev/null
@@ -1,90 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
-
- <PreferenceCategory
- android:key="account_settings">
-
- <EditTextPreference
- android:key="account_description"
- android:title="@string/account_settings_description_label"
- android:summary=""
- android:dialogTitle="@string/account_settings_description_label" />
-
- <EditTextPreference
- android:key="account_name"
- android:title="@string/account_settings_name_label"
- android:summary=""
- android:dialogTitle="@string/account_settings_name_label" />
-
- <ListPreference
- android:key="account_check_frequency"
- android:title="@string/account_settings_mail_check_frequency_label"
- android:entries="@array/account_settings_check_frequency_entries"
- android:entryValues="@array/account_settings_check_frequency_values"
- android:dialogTitle="@string/account_settings_mail_check_frequency_label" />
-
- <CheckBoxPreference
- android:key="account_default"
- android:title="@string/account_settings_default_label"
- android:summary="@string/account_settings_default_summary" />
-
- </PreferenceCategory>
-
- <PreferenceCategory android:title="@string/account_settings_notifications">
-
- <CheckBoxPreference
- android:key="account_notify"
- android:title="@string/account_settings_notify_label"
- android:defaultValue="true"
- android:summary="@string/account_settings_notify_summary" />
-
- <RingtonePreference
- android:layout="?android:attr/preferenceLayoutChild"
- android:dependency="account_notify"
- android:key="account_ringtone"
- android:title="@string/account_settings_ringtone"
- android:ringtoneType="notification"
- android:defaultValue="content://settings/system/notification_sound" />
-
- <CheckBoxPreference
- android:layout="?android:attr/preferenceLayoutChild"
- android:dependency="account_notify"
- android:key="account_vibrate"
- android:defaultValue="false"
- android:title="@string/account_settings_vibrate_enable"
- android:summary="@string/account_settings_vibrate_summary" />
-
- </PreferenceCategory>
-
- <PreferenceCategory android:title="@string/account_settings_servers">
-
- <PreferenceScreen
- android:key="incoming"
- android:title="@string/account_settings_incoming_label" />
-
- <PreferenceScreen
- android:key="outgoing"
- android:title="@string/account_settings_outgoing_label" />
-
- <PreferenceScreen
- android:key="add_account"
- android:title="@string/account_settings_add_account_label" />
-
- </PreferenceCategory>
-
-</PreferenceScreen>
diff --git a/res/xml/providers.xml b/res/xml/providers.xml
deleted file mode 100644
index 21fc17bc8..000000000
--- a/res/xml/providers.xml
+++ /dev/null
@@ -1,263 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
- <!--
- This file contains configuration data for commonly-used email providers.
-
- ==== CONTENT GUIDELINES ====
-
- This file should only be used for email providers that are considered "universal"
- and are appropriate for *all* android platform devices. These entries must be accessible
- from all networks. It should be reasonable for any user to obtain an account on these
- networks, and test accounts must be easily obtainable. No entries should be added
- that are device, product, or carrier-specific.
-
- Entries that are device, product or carrier-specific should be added as overlays
- in the appropriate providers_product.xml file.
-
- ==== FORMAT OF ENTRIES ====
-
- This file is used to specify providers that we know default settings for
- so that the user can set up their account by simply entering their email
- address and password.
-
- When a user starts this process, the email address is parsed, the domain
- broken out and used to search this file for a provider. If one is found the
- provider's settings are used to attempt to connect to the account.
-
- At this time, the id and label attributes are not used. However, please include them
- if you make edits to this file. id must also be completely unique. label will be shown
- to the user when there are multiple options provided for a single domain (not currently
- supported).
-
- A provider contains the settings for setting up an email account
- that ends with the given domain. Domains should be unique within
- this file. Each provider should have at least one incoming section and
- one outgoing section. If more than one is specified only the first
- will be used.
-
- Valid incoming uri schemes are:
- imap IMAP with no transport security.
- imap+tls IMAP with optional TLS transport security.
- If TLS is not available the connection is made as "imap"
- imap+tls+ IMAP with required TLS transport security.
- If TLS is not available the conneciton fails.
- imap+ssl+ IMAP with required SSL transport security.
- If SSL is not available the connection fails.
-
- pop3 POP3 with no transport security.
- pop3+tls POP3 with optional TLS transport security.
- If TLS is not available the connection is made as "pop3"
- pop3+tls+ POP3 with required TLS transport security.
- If TLS is not available the conneciton fails.
- pop3+ssl+ POP3 with required SSL transport security.
- If SSL is not available the connection fails.
-
- Valid outgoing uri schemes are:
- smtp SMTP with no transport security.
- smtp+tls SMTP with optional TLS transport security.
- If TLS is not available the connection is made as "smtp"
- smtp+tls+ SMTP with required TLS transport security.
- If TLS is not available the conneciton fails.
- smtp+ssl+ SMTP with required SSL transport security.
- If SSL is not available the connection fails.
-
- The URIs should be full templates for connection, including a port if
- the service uses a non-default port.
-
- The username attribute is used to supply a template for the username
- that will be presented to the server. This username is built from a
- set of variables that are substituted with parts of the user
- specified email address.
-
- Valid substitution values for the username attribute are:
- $email - the email address the user entered
- $user - the value before the @ sign in the email address the user entered
- $domain - the value after the @ signin the email address the user entered
-
- The username attribute MUST be specified for the incoming element, so the POP3 or IMAP
- server can identify the mailbox to be opened.
-
- The username attribute MAY be the empty string for the outgoing element, but only if the
- SMTP server supports anonymous transmission (most don't).
- -->
-
-<providers>
-
- <!-- Gmail variants -->
- <provider id="gmail" label="Gmail" domain="gmail.com">
- <incoming uri="imap+ssl+://imap.gmail.com" username="$email" />
- <outgoing uri="smtp+ssl+://smtp.gmail.com" username="$email" />
- </provider>
- <provider id="googlemail" label="Google Mail" domain="googlemail.com">
- <incoming uri="imap+ssl+://imap.googlemail.com" username="$email" />
- <outgoing uri="smtp+ssl+://smtp.googlemail.com" username="$email" />
- </provider>
- <provider id="google" label="Google" domain="google.com">
- <incoming uri="imap+ssl+://imap.gmail.com" username="$email" />
- <outgoing uri="smtp+ssl+://smtp.gmail.com" username="$email" />
- </provider>
- <provider id="android" label="Android" domain="android.com">
- <incoming uri="imap+ssl+://imap.gmail.com" username="$email" />
- <outgoing uri="smtp+ssl+://smtp.gmail.com" username="$email" />
- </provider>
-
- <!-- USA -->
- <provider id="aim" label="AIM" domain="aim.com">
- <incoming uri="imap://imap.aim.com" label="IMAP" username="$email" />
- <outgoing uri="smtp://smtp.aim.com:587" username="$email" />
- </provider>
- <provider id="aol" label="AOL" domain="aol.com">
- <incoming uri="imap://imap.aol.com" label="IMAP" username="$email" />
- <outgoing uri="smtp://smtp.aol.com:587" username="$email" />
- </provider>
- <provider id="comcast" label="Comcast" domain="comcast.net">
- <incoming uri="pop3+ssl+://mail.comcast.net" username="$user" />
- <outgoing uri="smtp+ssl+://smtp.comcast.net" username="$user" />
- </provider>
- <provider id="compuserve" label="CompuServe" domain="cs.com">
- <incoming uri="imap://imap.cs.com" username="$user" />
- <outgoing uri="smtp://smtp.cs.com" username="$user" />
- </provider>
- <provider id="dotmac" label=".Mac" domain="mac.com">
- <incoming uri="imap+tls://mail.mac.com" username="$email" />
- <outgoing uri="smtp+tls://smtp.mac.com" username="$email" />
- </provider>
- <provider id="earthlink" label="Earthlink" domain="earthlink.net">
- <incoming uri="pop3://pop.earthlink.net" username="$email" />
- <outgoing uri="smtp://smtpauth.earthlink.net:587" username="$email" />
- </provider>
- <provider id="juno" label="Juno" domain="juno.com">
- <incoming uri="pop3://pop.juno.com" username="$user" />
- <outgoing uri="smtp://smtp.juno.com" username="$user" />
- </provider>
- <provider id="live" label="Windows Live Hotmail Plus" domain="live.com"
- note="@string/provider_note_live">
- <incoming uri="pop3+ssl+://pop3.live.com" username="$email" />
- <outgoing uri="smtp+tls+://smtp.live.com" username="$email" />
- </provider>
- <provider id="hotmail" label="Windows Live Hotmail Plus" domain="hotmail.com"
- note="@string/provider_note_live">
- <incoming uri="pop3+ssl+://pop3.live.com" username="$email" />
- <outgoing uri="smtp+tls+://smtp.live.com" username="$email" />
- </provider>
- <provider id="msn" label="Windows Live Hotmail Plus" domain="msn.com"
- note="@string/provider_note_live">
- <incoming uri="pop3+ssl+://pop3.live.com" username="$email" />
- <outgoing uri="smtp+tls+://smtp.live.com" username="$email" />
- </provider>
- <provider id="mobileme" label="MobileMe" domain="me.com">
- <incoming uri="imap+tls://mail.me.com" username="$email" />
- <outgoing uri="smtp+tls://smtp.me.com" username="$email" />
- </provider>
- <provider id="netzero" label="NetZero" domain="netzero.com">
- <incoming uri="pop3://pop.netzero.com" username="$user" />
- <outgoing uri="smtp://smtp.netzero.com" username="$user" />
- </provider>
- <provider id="sbcglobal" label="SBC Global" domain="sbcglobal.net">
- <incoming uri="pop3://pop.sbcglobal.yahoo.com" username="$email" />
- <outgoing uri="smtp://smtp.sbcglobal.yahoo.com" username="$email" />
- </provider>
- <provider id="verizon" label="Verizon" domain="verizon.net">
- <incoming uri="pop3://incoming.verizon.net" username="$user" />
- <outgoing uri="smtp://outgoing.verizon.net" username="$user" />
- </provider>
- <provider id="yahoo" label="Yahoo Plus" domain="yahoo.com" note="@string/provider_note_yahoo">
- <incoming uri="pop3+ssl+://plus.pop.mail.yahoo.com" username="$user" />
- <outgoing uri="smtp+ssl+://plus.smtp.mail.yahoo.com" username="$user" />
- </provider>
-
- <!-- UK -->
- <provider id="aol-uk" label="AOL" domain="aol.co.uk">
- <incoming uri="imap+ssl+://imap.uk.aol.com" label="IMAP" username="$user" />
- <outgoing uri="smtp+ssl+://smtp.uk.aol.com" username="$user" />
- </provider>
- <provider id="bt" label="BT Internet" domain="btinternet.com">
- <incoming uri="pop3://mail.btinternet.com" username="$email" />
- <outgoing uri="smtp://mail.btinternet.com" username="" />
- </provider>
- <provider id="yahoo-uk" label="Yahoo" domain="yahoo.co.uk" note="@string/provider_note_yahoo_uk">
- <incoming uri="pop3+ssl+://pop.mail.yahoo.co.uk" username="$user" />
- <outgoing uri="smtp+ssl+://smtp.mail.yahoo.co.uk" username="$user" />
- </provider>
-
- <!-- Germany -->
- <provider id="freenet" label="Freenet" domain="freenet.de">
- <incoming uri="pop3://mx.freenet.de" username="$user" />
- <outgoing uri="smtp+ssl://mx.freenet.de" username="$email" />
- </provider>
- <provider id="gmx" label="GMX" domain="gmx.de">
- <incoming uri="pop3+tls://pop.gmx.net" username="$email" />
- <outgoing uri="smtp+tls://mail.gmx.net" username="$email" />
- </provider>
- <provider id="T-Online" label="T-Online" domain="t-online.de"
- note="@string/provider_note_t_online">
- <incoming uri="pop3://popmail.t-online.de" username="$email" />
- <outgoing uri="smtp://smtpmail.t-online.de" username="$email" />
- </provider>
- <provider id="web.de" label="Web.de" domain="web.de">
- <incoming uri="pop3+tls://pop3.web.de" username="$user" />
- <outgoing uri="smtp+tls://smtp.web.de" username="$user" />
- </provider>
-
- <!-- Netherlands -->
- <!-- TODO: For all of these, please confirm POP3, and switch to IMAP if supported -->
- <!-- TODO: username="" in incoming element is broken - will not work -->
- <!-- Disabled until username="" is resolved
- <provider id="hetnet" label="Het Net" domain="hetnet.nl">
- <incoming uri="pop3://pop.hetnet.nl" username="" />
- <outgoing uri="smtp://mailhost.hetnet.nl" username="" />
- </provider>
- -->
- <!-- Disabled until test accounts provided
- <provider id="planet inet" label="Planet Internet" domain="planet.nl">
- <incoming uri="pop3://pop.planet.nl" username="$user" />
- <outgoing uri="smtp://mail.planet.nl" username="" />
- </provider>
- -->
- <!-- TODO: username="" in incoming element is broken - will not work -->
- <!-- Disabled until username="" is resolved
- <provider id="tiscali" label="Tiscali" domain="tiscali.nl">
- <incoming uri="pop3://pop3.tiscali.nl" username="" />
- <outgoing uri="smtp://smtp.tiscali.nl" username="" />
- </provider>
- -->
- <!-- Disabled until test accounts provided
- <provider id="wanadoo" label="Wanadoo" domain="wanadoo.nl">
- <incoming uri="pop3://pop.wanadoo.nl" username="$user" />
- <outgoing uri="smtp://smtp.wanadoo.nl" username="$user" />
- </provider>
- -->
-
- <!-- Poland -->
- <provider id="onet" label="Onet.pl" domain="poczta.onet.pl">
- <incoming uri="pop3://pop3.poczta.onet.pl" username="$email" />
- <outgoing uri="smtp://smtp.poczta.onet.pl" username="$email" />
- </provider>
- <provider id="wirtualna" label="Wirtualna Polska" domain="wp.pl">
- <incoming uri="pop3://pop3.wp.pl" username="$user" />
- <outgoing uri="smtp://smtp.wp.pl" username="$user" />
- </provider>
- <provider id="interia" label="Interia" domain="interia.pl">
- <incoming uri="pop3+ssl://poczta.interia.pl" username="$user" />
- <outgoing uri="smtp+ssl://poczta.interia.pl" username="$user" />
- </provider>
- <provider id="o2" label="O2" domain="o2.pl">
- <incoming uri="pop3+ssl://poczta.o2.pl" username="$user" />
- <outgoing uri="smtp+ssl://poczta.o2.pl" username="$user" />
- </provider>
-
-</providers>
diff --git a/res/xml/providers_product.xml b/res/xml/providers_product.xml
deleted file mode 100644
index f10382dfb..000000000
--- a/res/xml/providers_product.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
- <!--
- Email providers that are considered "universal" and are appropriate for *all* android
- platform devices should be defined in providers.xml.
-
- Entries that are device, product or carrier-specific should be added as overlays
- in the appropriate providers_product.xml file.
-
- Because overlays must correspond to an existing platform resource, this empty placeholder
- is included in the platform build.
- -->
-
-<providers_product>
-
- <!-- THIS SECTION MUST REMAIN EMPTY -->
-
-</providers_product>
diff --git a/src/com/android/email/Account.java b/src/com/android/email/Account.java
deleted file mode 100644
index 2d98ce3ab..000000000
--- a/src/com/android/email/Account.java
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email;
-
-import com.android.email.mail.Store;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.net.Uri;
-
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.UUID;
-
-/**
- * Account stores all of the settings for a single account defined by the user. It is able to save
- * and delete itself given a Preferences to work with. Each account is defined by a UUID.
- */
-public class Account implements Serializable {
- public static final int DELETE_POLICY_NEVER = 0;
- public static final int DELETE_POLICY_7DAYS = 1;
- public static final int DELETE_POLICY_ON_DELETE = 2;
-
- private static final long serialVersionUID = 2975156672298625121L;
-
- String mUuid;
- String mStoreUri;
- String mLocalStoreUri;
- String mSenderUri;
- String mDescription;
- String mName;
- String mEmail;
- int mAutomaticCheckIntervalMinutes;
- long mLastAutomaticCheckTime;
- boolean mNotifyNewMail;
- String mDraftsFolderName;
- String mSentFolderName;
- String mTrashFolderName;
- String mOutboxFolderName;
- int mAccountNumber;
- boolean mVibrate;
- String mRingtoneUri;
-
- /**
- * <pre>
- * 0 Never
- * 1 After 7 days
- * 2 When I delete from inbox
- * </pre>
- */
- int mDeletePolicy;
-
- public Account(Context context) {
- // TODO Change local store path to something readable / recognizable
- mUuid = UUID.randomUUID().toString();
- mLocalStoreUri = "local://localhost/" + context.getDatabasePath(mUuid + ".db");
- mAutomaticCheckIntervalMinutes = -1;
- mAccountNumber = -1;
- mNotifyNewMail = true;
- mVibrate = false;
- mRingtoneUri = "content://settings/system/notification_sound";
- }
-
- Account(Preferences preferences, String uuid) {
- this.mUuid = uuid;
- refresh(preferences);
- }
-
- /**
- * Refresh the account from the stored settings.
- */
- public void refresh(Preferences preferences) {
- mStoreUri = Utility.base64Decode(preferences.mSharedPreferences.getString(mUuid
- + ".storeUri", null));
- mLocalStoreUri = preferences.mSharedPreferences.getString(mUuid + ".localStoreUri", null);
-
- String senderText = preferences.mSharedPreferences.getString(mUuid + ".senderUri", null);
- if (senderText == null) {
- // Preference ".senderUri" was called ".transportUri" in earlier versions, so we'll
- // do a simple upgrade here when necessary.
- senderText = preferences.mSharedPreferences.getString(mUuid + ".transportUri", null);
- }
- mSenderUri = Utility.base64Decode(senderText);
-
- mDescription = preferences.mSharedPreferences.getString(mUuid + ".description", null);
- mName = preferences.mSharedPreferences.getString(mUuid + ".name", mName);
- mEmail = preferences.mSharedPreferences.getString(mUuid + ".email", mEmail);
- mAutomaticCheckIntervalMinutes = preferences.mSharedPreferences.getInt(mUuid
- + ".automaticCheckIntervalMinutes", -1);
- mLastAutomaticCheckTime = preferences.mSharedPreferences.getLong(mUuid
- + ".lastAutomaticCheckTime", 0);
- mNotifyNewMail = preferences.mSharedPreferences.getBoolean(mUuid + ".notifyNewMail",
- false);
-
- // delete policy was incorrectly set on earlier versions, so we'll upgrade it here.
- // rule: if IMAP account and policy = 0 ("never"), change policy to 2 ("on delete")
- mDeletePolicy = preferences.mSharedPreferences.getInt(mUuid + ".deletePolicy", 0);
- if (mDeletePolicy == DELETE_POLICY_NEVER &&
- mStoreUri != null && mStoreUri.toString().startsWith(Store.STORE_SCHEME_IMAP)) {
- mDeletePolicy = DELETE_POLICY_ON_DELETE;
- }
-
- mDraftsFolderName = preferences.mSharedPreferences.getString(mUuid + ".draftsFolderName",
- "Drafts");
- mSentFolderName = preferences.mSharedPreferences.getString(mUuid + ".sentFolderName",
- "Sent");
- mTrashFolderName = preferences.mSharedPreferences.getString(mUuid + ".trashFolderName",
- "Trash");
- mOutboxFolderName = preferences.mSharedPreferences.getString(mUuid + ".outboxFolderName",
- "Outbox");
- mAccountNumber = preferences.mSharedPreferences.getInt(mUuid + ".accountNumber", 0);
- mVibrate = preferences.mSharedPreferences.getBoolean(mUuid + ".vibrate", false);
- mRingtoneUri = preferences.mSharedPreferences.getString(mUuid + ".ringtone",
- "content://settings/system/notification_sound");
- }
-
- public String getUuid() {
- return mUuid;
- }
-
- public String getStoreUri() {
- return mStoreUri;
- }
-
- public void setStoreUri(String storeUri) {
- this.mStoreUri = storeUri;
- }
-
- public String getSenderUri() {
- return mSenderUri;
- }
-
- public void setSenderUri(String senderUri) {
- this.mSenderUri = senderUri;
- }
-
- public String getDescription() {
- return mDescription;
- }
-
- public void setDescription(String description) {
- this.mDescription = description;
- }
-
- public String getName() {
- return mName;
- }
-
- public void setName(String name) {
- this.mName = name;
- }
-
- public String getEmail() {
- return mEmail;
- }
-
- public void setEmail(String email) {
- this.mEmail = email;
- }
-
- public boolean isVibrate() {
- return mVibrate;
- }
-
- public void setVibrate(boolean vibrate) {
- mVibrate = vibrate;
- }
-
- public String getRingtone() {
- return mRingtoneUri;
- }
-
- public void setRingtone(String ringtoneUri) {
- mRingtoneUri = ringtoneUri;
- }
-
- public void delete(Preferences preferences) {
- String[] uuids = preferences.mSharedPreferences.getString("accountUuids", "").split(",");
- StringBuffer sb = new StringBuffer();
- for (int i = 0, length = uuids.length; i < length; i++) {
- if (!uuids[i].equals(mUuid)) {
- if (sb.length() > 0) {
- sb.append(',');
- }
- sb.append(uuids[i]);
- }
- }
- String accountUuids = sb.toString();
- SharedPreferences.Editor editor = preferences.mSharedPreferences.edit();
- editor.putString("accountUuids", accountUuids);
-
- editor.remove(mUuid + ".storeUri");
- editor.remove(mUuid + ".localStoreUri");
- editor.remove(mUuid + ".senderUri");
- editor.remove(mUuid + ".description");
- editor.remove(mUuid + ".name");
- editor.remove(mUuid + ".email");
- editor.remove(mUuid + ".automaticCheckIntervalMinutes");
- editor.remove(mUuid + ".lastAutomaticCheckTime");
- editor.remove(mUuid + ".notifyNewMail");
- editor.remove(mUuid + ".deletePolicy");
- editor.remove(mUuid + ".draftsFolderName");
- editor.remove(mUuid + ".sentFolderName");
- editor.remove(mUuid + ".trashFolderName");
- editor.remove(mUuid + ".outboxFolderName");
- editor.remove(mUuid + ".accountNumber");
- editor.remove(mUuid + ".vibrate");
- editor.remove(mUuid + ".ringtone");
-
- // also delete any deprecated fields
- editor.remove(mUuid + ".transportUri");
-
- editor.commit();
- }
-
- public void save(Preferences preferences) {
- if (!preferences.mSharedPreferences.getString("accountUuids", "").contains(mUuid)) {
- /*
- * When the account is first created we assign it a unique account number. The
- * account number will be unique to that account for the lifetime of the account.
- * So, we get all the existing account numbers, sort them ascending, loop through
- * the list and check if the number is greater than 1 + the previous number. If so
- * we use the previous number + 1 as the account number. This refills gaps.
- * mAccountNumber starts as -1 on a newly created account. It must be -1 for this
- * algorithm to work.
- *
- * I bet there is a much smarter way to do this. Anyone like to suggest it?
- */
- Account[] accounts = preferences.getAccounts();
- int[] accountNumbers = new int[accounts.length];
- for (int i = 0; i < accounts.length; i++) {
- accountNumbers[i] = accounts[i].getAccountNumber();
- }
- Arrays.sort(accountNumbers);
- for (int accountNumber : accountNumbers) {
- if (accountNumber > mAccountNumber + 1) {
- break;
- }
- mAccountNumber = accountNumber;
- }
- mAccountNumber++;
-
- String accountUuids = preferences.mSharedPreferences.getString("accountUuids", "");
- accountUuids += (accountUuids.length() != 0 ? "," : "") + mUuid;
- SharedPreferences.Editor editor = preferences.mSharedPreferences.edit();
- editor.putString("accountUuids", accountUuids);
- editor.commit();
- }
-
- SharedPreferences.Editor editor = preferences.mSharedPreferences.edit();
-
- editor.putString(mUuid + ".storeUri", Utility.base64Encode(mStoreUri));
- editor.putString(mUuid + ".localStoreUri", mLocalStoreUri);
- editor.putString(mUuid + ".senderUri", Utility.base64Encode(mSenderUri));
- editor.putString(mUuid + ".description", mDescription);
- editor.putString(mUuid + ".name", mName);
- editor.putString(mUuid + ".email", mEmail);
- editor.putInt(mUuid + ".automaticCheckIntervalMinutes", mAutomaticCheckIntervalMinutes);
- editor.putLong(mUuid + ".lastAutomaticCheckTime", mLastAutomaticCheckTime);
- editor.putBoolean(mUuid + ".notifyNewMail", mNotifyNewMail);
- editor.putInt(mUuid + ".deletePolicy", mDeletePolicy);
- editor.putString(mUuid + ".draftsFolderName", mDraftsFolderName);
- editor.putString(mUuid + ".sentFolderName", mSentFolderName);
- editor.putString(mUuid + ".trashFolderName", mTrashFolderName);
- editor.putString(mUuid + ".outboxFolderName", mOutboxFolderName);
- editor.putInt(mUuid + ".accountNumber", mAccountNumber);
- editor.putBoolean(mUuid + ".vibrate", mVibrate);
- editor.putString(mUuid + ".ringtone", mRingtoneUri);
-
- // also delete any deprecated fields
- editor.remove(mUuid + ".transportUri");
-
- editor.commit();
- }
-
- public String toString() {
- return mDescription;
- }
-
- public Uri getContentUri() {
- return Uri.parse("content://accounts/" + getUuid());
- }
-
- public String getLocalStoreUri() {
- return mLocalStoreUri;
- }
-
- public void setLocalStoreUri(String localStoreUri) {
- this.mLocalStoreUri = localStoreUri;
- }
-
- /**
- * Returns -1 for never.
- */
- public int getAutomaticCheckIntervalMinutes() {
- return mAutomaticCheckIntervalMinutes;
- }
-
- /**
- * @param automaticCheckIntervalMinutes or -1 for never.
- */
- public void setAutomaticCheckIntervalMinutes(int automaticCheckIntervalMinutes) {
- this.mAutomaticCheckIntervalMinutes = automaticCheckIntervalMinutes;
- }
-
- public long getLastAutomaticCheckTime() {
- return mLastAutomaticCheckTime;
- }
-
- public void setLastAutomaticCheckTime(long lastAutomaticCheckTime) {
- this.mLastAutomaticCheckTime = lastAutomaticCheckTime;
- }
-
- public boolean isNotifyNewMail() {
- return mNotifyNewMail;
- }
-
- public void setNotifyNewMail(boolean notifyNewMail) {
- this.mNotifyNewMail = notifyNewMail;
- }
-
- public int getDeletePolicy() {
- return mDeletePolicy;
- }
-
- public void setDeletePolicy(int deletePolicy) {
- this.mDeletePolicy = deletePolicy;
- }
-
- public String getDraftsFolderName() {
- return mDraftsFolderName;
- }
-
- public void setDraftsFolderName(String draftsFolderName) {
- mDraftsFolderName = draftsFolderName;
- }
-
- public String getSentFolderName() {
- return mSentFolderName;
- }
-
- public void setSentFolderName(String sentFolderName) {
- mSentFolderName = sentFolderName;
- }
-
- public String getTrashFolderName() {
- return mTrashFolderName;
- }
-
- public void setTrashFolderName(String trashFolderName) {
- mTrashFolderName = trashFolderName;
- }
-
- public String getOutboxFolderName() {
- return mOutboxFolderName;
- }
-
- public void setOutboxFolderName(String outboxFolderName) {
- mOutboxFolderName = outboxFolderName;
- }
-
- public int getAccountNumber() {
- return mAccountNumber;
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof Account) {
- return ((Account)o).mUuid.equals(mUuid);
- }
- return super.equals(o);
- }
-}
diff --git a/src/com/android/email/Email.java b/src/com/android/email/Email.java
deleted file mode 100644
index 81aae8e2b..000000000
--- a/src/com/android/email/Email.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email;
-
-import com.android.email.activity.AccountShortcutPicker;
-import com.android.email.activity.MessageCompose;
-import com.android.email.mail.internet.BinaryTempFileBody;
-import com.android.email.service.BootReceiver;
-import com.android.email.service.MailService;
-
-import android.app.Application;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-
-import java.io.File;
-
-public class Email extends Application {
- public static final String LOG_TAG = "Email";
-
- public static File tempDirectory;
-
- /**
- * If this is enabled there will be additional logging information sent to
- * Log.d, including protocol dumps.
- */
- public static boolean DEBUG = false;
-
- /**
- * If this is enabled than logging that normally hides sensitive information
- * like passwords will show that information.
- */
- public static boolean DEBUG_SENSITIVE = false;
-
- /**
- * The MIME type(s) of attachments we're willing to send. At the moment it is not possible
- * to open a chooser with a list of filter types, so the chooser is only opened with the first
- * item in the list. The entire list will be used to filter down attachments that are added
- * with Intent.ACTION_SEND.
- *
- * TODO: It should be legal to send anything requested by another app. This would provide
- * parity with Gmail's behavior.
- */
- public static final String[] ACCEPTABLE_ATTACHMENT_SEND_TYPES = new String[] {
- "image/*",
- "video/*",
- };
-
- /**
- * The MIME type(s) of attachments we're willing to view.
- */
- public static final String[] ACCEPTABLE_ATTACHMENT_VIEW_TYPES = new String[] {
- "image/*",
- "audio/*",
- "text/*",
- };
-
- /**
- * The MIME type(s) of attachments we're not willing to view.
- */
- public static final String[] UNACCEPTABLE_ATTACHMENT_VIEW_TYPES = new String[] {
- "image/gif",
- };
-
- /**
- * The MIME type(s) of attachments we're willing to download to SD.
- */
- public static final String[] ACCEPTABLE_ATTACHMENT_DOWNLOAD_TYPES = new String[] {
- "image/*",
- };
-
- /**
- * The MIME type(s) of attachments we're not willing to download to SD.
- */
- public static final String[] UNACCEPTABLE_ATTACHMENT_DOWNLOAD_TYPES = new String[] {
- "image/gif",
- };
-
- /**
- * The special name "INBOX" is used throughout the application to mean "Whatever folder
- * the server refers to as the user's Inbox. Placed here to ease use.
- */
- public static final String INBOX = "INBOX";
-
- /**
- * Specifies how many messages will be shown in a folder by default. This number is set
- * on each new folder and can be incremented with "Load more messages..." by the
- * VISIBLE_LIMIT_INCREMENT
- */
- public static final int DEFAULT_VISIBLE_LIMIT = 25;
-
- /**
- * Number of additioanl messages to load when a user selectes "Load more messages..."
- */
- public static final int VISIBLE_LIMIT_INCREMENT = 25;
-
- /**
- * The maximum size of an attachment we're willing to download (either View or Save)
- * Attachments that are base64 encoded (most) will be about 1.375x their actual size
- * so we should probably factor that in. A 5MB attachment will generally be around
- * 6.8MB downloaded but only 5MB saved.
- */
- public static final int MAX_ATTACHMENT_DOWNLOAD_SIZE = (5 * 1024 * 1024);
-
- /**
- * Called throughout the application when the number of accounts has changed. This method
- * enables or disables the Compose activity, the boot receiver and the service based on
- * whether any accounts are configured.
- */
- public static void setServicesEnabled(Context context) {
- setServicesEnabled(context, Preferences.getPreferences(context).getAccounts().length > 0);
- }
-
- public static void setServicesEnabled(Context context, boolean enabled) {
- PackageManager pm = context.getPackageManager();
- if (!enabled && pm.getComponentEnabledSetting(new ComponentName(context, MailService.class)) ==
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
- /*
- * If no accounts now exist but the service is still enabled we're about to disable it
- * so we'll reschedule to kill off any existing alarms.
- */
- MailService.actionReschedule(context);
- }
- pm.setComponentEnabledSetting(
- new ComponentName(context, MessageCompose.class),
- enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- pm.setComponentEnabledSetting(
- new ComponentName(context, AccountShortcutPicker.class),
- enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- pm.setComponentEnabledSetting(
- new ComponentName(context, BootReceiver.class),
- enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- pm.setComponentEnabledSetting(
- new ComponentName(context, MailService.class),
- enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- if (enabled && pm.getComponentEnabledSetting(new ComponentName(context, MailService.class)) ==
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
- /*
- * And now if accounts do exist then we've just enabled the service and we want to
- * schedule alarms for the new accounts.
- */
- MailService.actionReschedule(context);
- }
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- Preferences prefs = Preferences.getPreferences(this);
- DEBUG = prefs.geteEnableDebugLogging();
- DEBUG_SENSITIVE = prefs.getEnableSensitiveLogging();
- MessagingController.getInstance(this).resetVisibleLimits(prefs.getAccounts());
-
- /*
- * We have to give MimeMessage a temp directory because File.createTempFile(String, String)
- * doesn't work in Android and MimeMessage does not have access to a Context.
- */
- BinaryTempFileBody.setTempDirectory(getCacheDir());
- }
-}
-
-
-
-
-
-
-
-
diff --git a/src/com/android/email/EmailAddressAdapter.java b/src/com/android/email/EmailAddressAdapter.java
deleted file mode 100644
index 45636c0b9..000000000
--- a/src/com/android/email/EmailAddressAdapter.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email;
-
-import static android.provider.Contacts.ContactMethods.CONTENT_EMAIL_URI;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.provider.Contacts.ContactMethods;
-import android.provider.Contacts.People;
-import android.view.View;
-import android.widget.ResourceCursorAdapter;
-import android.widget.TextView;
-
-import com.android.email.mail.Address;
-
-public class EmailAddressAdapter extends ResourceCursorAdapter {
- public static final int NAME_INDEX = 1;
-
- public static final int DATA_INDEX = 2;
-
- private static final String SORT_ORDER = People.TIMES_CONTACTED + " DESC, " + People.NAME;
-
- private ContentResolver mContentResolver;
-
- private static final String[] PROJECTION = {
- ContactMethods._ID, // 0
- ContactMethods.NAME, // 1
- ContactMethods.DATA
- // 2
- };
-
- public EmailAddressAdapter(Context context) {
- super(context, R.layout.recipient_dropdown_item, null);
- mContentResolver = context.getContentResolver();
- }
-
- @Override
- public final String convertToString(Cursor cursor) {
- String name = cursor.getString(NAME_INDEX);
- String address = cursor.getString(DATA_INDEX);
-
- return new Address(address, name).toString();
- }
-
- @Override
- public final void bindView(View view, Context context, Cursor cursor) {
- TextView text1 = (TextView)view.findViewById(R.id.text1);
- TextView text2 = (TextView)view.findViewById(R.id.text2);
- text1.setText(cursor.getString(NAME_INDEX));
- text2.setText(cursor.getString(DATA_INDEX));
- }
-
- @Override
- public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
- String where = null;
-
- if (constraint != null) {
- String filter = DatabaseUtils.sqlEscapeString(constraint.toString() + '%');
-
- StringBuilder s = new StringBuilder();
- s.append("(people.name LIKE ");
- s.append(filter);
- s.append(") OR (contact_methods.data LIKE ");
- s.append(filter);
- s.append(")");
-
- where = s.toString();
- }
-
- return mContentResolver.query(CONTENT_EMAIL_URI, PROJECTION, where, null, SORT_ORDER);
- }
-}
diff --git a/src/com/android/email/EmailAddressValidator.java b/src/com/android/email/EmailAddressValidator.java
deleted file mode 100644
index e6aab2f96..000000000
--- a/src/com/android/email/EmailAddressValidator.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email;
-
-import com.android.email.mail.Address;
-
-import android.util.Config;
-import android.util.Log;
-import android.widget.AutoCompleteTextView.Validator;
-
-public class EmailAddressValidator implements Validator {
- public CharSequence fixText(CharSequence invalidText) {
- return "";
- }
-
- public boolean isValid(CharSequence text) {
- return Address.parse(text.toString()).length > 0;
- }
-}
diff --git a/src/com/android/email/FixedLengthInputStream.java b/src/com/android/email/FixedLengthInputStream.java
deleted file mode 100644
index bac33758f..000000000
--- a/src/com/android/email/FixedLengthInputStream.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * A filtering InputStream that stops allowing reads after the given length has been read. This
- * is used to allow a client to read directly from an underlying protocol stream without reading
- * past where the protocol handler intended the client to read.
- */
-public class FixedLengthInputStream extends InputStream {
- private InputStream mIn;
- private int mLength;
- private int mCount;
-
- public FixedLengthInputStream(InputStream in, int length) {
- this.mIn = in;
- this.mLength = length;
- }
-
- @Override
- public int available() throws IOException {
- return mLength - mCount;
- }
-
- @Override
- public int read() throws IOException {
- if (mCount < mLength) {
- mCount++;
- return mIn.read();
- } else {
- return -1;
- }
- }
-
- @Override
- public int read(byte[] b, int offset, int length) throws IOException {
- if (mCount < mLength) {
- int d = mIn.read(b, offset, Math.min(mLength - mCount, length));
- if (d == -1) {
- return -1;
- } else {
- mCount += d;
- return d;
- }
- } else {
- return -1;
- }
- }
-
- @Override
- public int read(byte[] b) throws IOException {
- return read(b, 0, b.length);
- }
-
- public String toString() {
- return String.format("FixedLengthInputStream(in=%s, length=%d)", mIn.toString(), mLength);
- }
-}
diff --git a/src/com/android/email/MessagingController.java b/src/com/android/email/MessagingController.java
deleted file mode 100644
index 5da63b449..000000000
--- a/src/com/android/email/MessagingController.java
+++ /dev/null
@@ -1,1479 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-
-import android.app.Application;
-import android.content.Context;
-import android.os.Process;
-import android.util.Config;
-import android.util.Log;
-
-import com.android.email.mail.FetchProfile;
-import com.android.email.mail.Flag;
-import com.android.email.mail.Folder;
-import com.android.email.mail.Message;
-import com.android.email.mail.MessageRetrievalListener;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Part;
-import com.android.email.mail.Sender;
-import com.android.email.mail.Store;
-import com.android.email.mail.Folder.FolderType;
-import com.android.email.mail.Folder.OpenMode;
-import com.android.email.mail.internet.MimeUtility;
-import com.android.email.mail.store.LocalStore;
-import com.android.email.mail.store.LocalStore.LocalFolder;
-import com.android.email.mail.store.LocalStore.LocalMessage;
-import com.android.email.mail.store.LocalStore.PendingCommand;
-
-/**
- * Starts a long running (application) Thread that will run through commands
- * that require remote mailbox access. This class is used to serialize and
- * prioritize these commands. Each method that will submit a command requires a
- * MessagingListener instance to be provided. It is expected that that listener
- * has also been added as a registered listener using addListener(). When a
- * command is to be executed, if the listener that was provided with the command
- * is no longer registered the command is skipped. The design idea for the above
- * is that when an Activity starts it registers as a listener. When it is paused
- * it removes itself. Thus, any commands that that activity submitted are
- * removed from the queue once the activity is no longer active.
- */
-public class MessagingController implements Runnable {
- /**
- * The maximum message size that we'll consider to be "small". A small message is downloaded
- * in full immediately instead of in pieces. Anything over this size will be downloaded in
- * pieces with attachments being left off completely and downloaded on demand.
- *
- *
- * 25k for a "small" message was picked by educated trial and error.
- * http://answers.google.com/answers/threadview?id=312463 claims that the
- * average size of an email is 59k, which I feel is too large for our
- * blind download. The following tests were performed on a download of
- * 25 random messages.
- * <pre>
- * 5k - 61 seconds,
- * 25k - 51 seconds,
- * 55k - 53 seconds,
- * </pre>
- * So 25k gives good performance and a reasonable data footprint. Sounds good to me.
- */
- private static final int MAX_SMALL_MESSAGE_SIZE = (25 * 1024);
-
- private static final String PENDING_COMMAND_TRASH =
- "com.android.email.MessagingController.trash";
- private static final String PENDING_COMMAND_MARK_READ =
- "com.android.email.MessagingController.markRead";
- private static final String PENDING_COMMAND_APPEND =
- "com.android.email.MessagingController.append";
-
- private static MessagingController inst = null;
- private BlockingQueue<Command> mCommands = new LinkedBlockingQueue<Command>();
- private Thread mThread;
- private HashSet<MessagingListener> mListeners = new HashSet<MessagingListener>();
- private boolean mBusy;
- private Application mApplication;
-
- protected MessagingController(Application application) {
- mApplication = application;
- mThread = new Thread(this);
- mThread.start();
- }
-
- /**
- * Gets or creates the singleton instance of MessagingController. Application is used to
- * provide a Context to classes that need it.
- * @param application
- * @return
- */
- public synchronized static MessagingController getInstance(Application application) {
- if (inst == null) {
- inst = new MessagingController(application);
- }
- return inst;
- }
-
- /**
- * Inject a mock controller. Used only for testing. Affects future calls to getInstance().
- */
- public static void injectMockController(MessagingController mockController) {
- inst = mockController;
- }
-
- public boolean isBusy() {
- return mBusy;
- }
-
- public void run() {
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- while (true) {
- try {
- Command command = mCommands.take();
- if (command.listener == null || mListeners.contains(command.listener)) {
- mBusy = true;
- command.runnable.run();
- for (MessagingListener l : mListeners) {
- l.controllerCommandCompleted(mCommands.size() > 0);
- }
- }
- }
- catch (Exception e) {
- if (Config.LOGD) {
- Log.d(Email.LOG_TAG, "Error running command", e);
- }
- }
- mBusy = false;
- }
- }
-
- private void put(String description, MessagingListener listener, Runnable runnable) {
- try {
- Command command = new Command();
- command.listener = listener;
- command.runnable = runnable;
- command.description = description;
- mCommands.put(command);
- }
- catch (InterruptedException ie) {
- throw new Error(ie);
- }
- }
-
- public void addListener(MessagingListener listener) {
- mListeners.add(listener);
- }
-
- public void removeListener(MessagingListener listener) {
- mListeners.remove(listener);
- }
-
- /**
- * Lists folders that are available locally and remotely. This method calls
- * listFoldersCallback for local folders before it returns, and then for
- * remote folders at some later point. If there are no local folders
- * includeRemote is forced by this method. This method should be called from
- * a Thread as it may take several seconds to list the local folders. TODO
- * this needs to cache the remote folder list
- *
- * @param account
- * @param includeRemote
- * @param listener
- * @throws MessagingException
- */
- public void listFolders(
- final Account account,
- boolean refreshRemote,
- MessagingListener listener) {
- for (MessagingListener l : mListeners) {
- l.listFoldersStarted(account);
- }
- try {
- Store localStore = Store.getInstance(account.getLocalStoreUri(), mApplication);
- Folder[] localFolders = localStore.getPersonalNamespaces();
-
- if (localFolders == null || localFolders.length == 0) {
- refreshRemote = true;
- } else {
- for (MessagingListener l : mListeners) {
- l.listFolders(account, localFolders);
- }
- }
- }
- catch (Exception e) {
- for (MessagingListener l : mListeners) {
- l.listFoldersFailed(account, e.getMessage());
- return;
- }
- }
- if (refreshRemote) {
- put("listFolders", listener, new Runnable() {
- public void run() {
- try {
- Store store = Store.getInstance(account.getStoreUri(), mApplication);
-
- Folder[] remoteFolders = store.getPersonalNamespaces();
-
- Store localStore = Store.getInstance(
- account.getLocalStoreUri(),
- mApplication);
- HashSet<String> remoteFolderNames = new HashSet<String>();
- for (int i = 0, count = remoteFolders.length; i < count; i++) {
- Folder localFolder = localStore.getFolder(remoteFolders[i].getName());
- if (!localFolder.exists()) {
- localFolder.create(FolderType.HOLDS_MESSAGES);
- }
- remoteFolderNames.add(remoteFolders[i].getName());
- }
-
- Folder[] localFolders = localStore.getPersonalNamespaces();
-
- /*
- * Clear out any folders that are no longer on the remote store.
- */
- for (Folder localFolder : localFolders) {
- String localFolderName = localFolder.getName();
- if (localFolderName.equalsIgnoreCase(Email.INBOX) ||
- localFolderName.equals(account.getTrashFolderName()) ||
- localFolderName.equals(account.getOutboxFolderName()) ||
- localFolderName.equals(account.getDraftsFolderName()) ||
- localFolderName.equals(account.getSentFolderName())) {
- continue;
- }
- if (!remoteFolderNames.contains(localFolder.getName())) {
- localFolder.delete(false);
- }
- }
-
- localFolders = localStore.getPersonalNamespaces();
-
- for (MessagingListener l : mListeners) {
- l.listFolders(account, localFolders);
- }
- for (MessagingListener l : mListeners) {
- l.listFoldersFinished(account);
- }
- }
- catch (Exception e) {
- for (MessagingListener l : mListeners) {
- l.listFoldersFailed(account, "");
- }
- }
- }
- });
- } else {
- for (MessagingListener l : mListeners) {
- l.listFoldersFinished(account);
- }
- }
- }
-
- /**
- * List the local message store for the given folder. This work is done
- * synchronously.
- *
- * @param account
- * @param folder
- * @param listener
- * @throws MessagingException
- */
- public void listLocalMessages(final Account account, final String folder,
- MessagingListener listener) {
- for (MessagingListener l : mListeners) {
- l.listLocalMessagesStarted(account, folder);
- }
-
- try {
- Store localStore = Store.getInstance(account.getLocalStoreUri(), mApplication);
- Folder localFolder = localStore.getFolder(folder);
- localFolder.open(OpenMode.READ_WRITE);
- Message[] localMessages = localFolder.getMessages(null);
- ArrayList<Message> messages = new ArrayList<Message>();
- for (Message message : localMessages) {
- if (!message.isSet(Flag.DELETED)) {
- messages.add(message);
- }
- }
- for (MessagingListener l : mListeners) {
- l.listLocalMessages(account, folder, messages.toArray(new Message[0]));
- }
- for (MessagingListener l : mListeners) {
- l.listLocalMessagesFinished(account, folder);
- }
- }
- catch (Exception e) {
- for (MessagingListener l : mListeners) {
- l.listLocalMessagesFailed(account, folder, e.getMessage());
- }
- }
- }
-
- public void loadMoreMessages(Account account, String folder, MessagingListener listener) {
- try {
- LocalStore localStore = (LocalStore) Store.getInstance(
- account.getLocalStoreUri(),
- mApplication);
- LocalFolder localFolder = (LocalFolder) localStore.getFolder(folder);
- localFolder.setVisibleLimit(localFolder.getVisibleLimit()
- + Email.VISIBLE_LIMIT_INCREMENT);
- synchronizeMailbox(account, folder, listener);
- }
- catch (MessagingException me) {
- throw new RuntimeException("Unable to set visible limit on folder", me);
- }
- }
-
- public void resetVisibleLimits(Account[] accounts) {
- for (Account account : accounts) {
- try {
- LocalStore localStore =
- (LocalStore) Store.getInstance(account.getLocalStoreUri(), mApplication);
- localStore.resetVisibleLimits();
- }
- catch (MessagingException e) {
- Log.e(Email.LOG_TAG, "Unable to reset visible limits", e);
- }
- }
- }
-
- /**
- * Start background synchronization of the specified folder.
- * @param account
- * @param folder
- * @param numNewestMessagesToKeep Specifies the number of messages that should be
- * considered as part of the window of available messages. This number effectively limits
- * the user's view into the mailbox to the newest (numNewestMessagesToKeep) messages.
- * @param listener
- */
- public void synchronizeMailbox(final Account account, final String folder,
- MessagingListener listener) {
- /*
- * We don't ever sync the Outbox.
- */
- if (folder.equals(account.getOutboxFolderName())) {
- return;
- }
- for (MessagingListener l : mListeners) {
- l.synchronizeMailboxStarted(account, folder);
- }
- put("synchronizeMailbox", listener, new Runnable() {
- public void run() {
- synchronizeMailboxSyncronous(account, folder);
- }
- });
- }
-
- /**
- * Start foreground synchronization of the specified folder. This is generally only called
- * by synchronizeMailbox.
- * @param account
- * @param folder
- * @param numNewestMessagesToKeep Specifies the number of messages that should be
- * considered as part of the window of available messages. This number effectively limits
- * the user's view into the mailbox to the newest (numNewestMessagesToKeep) messages.
- * @param listener
- *
- * TODO Break this method up into smaller chunks.
- */
- public void synchronizeMailboxSyncronous(final Account account, final String folder) {
- for (MessagingListener l : mListeners) {
- l.synchronizeMailboxStarted(account, folder);
- }
- try {
- processPendingCommandsSynchronous(account);
-
- /*
- * Get the message list from the local store and create an index of
- * the uids within the list.
- */
- final LocalStore localStore =
- (LocalStore) Store.getInstance(account.getLocalStoreUri(), mApplication);
- final LocalFolder localFolder = (LocalFolder) localStore.getFolder(folder);
- localFolder.open(OpenMode.READ_WRITE);
- Message[] localMessages = localFolder.getMessages(null);
- HashMap<String, Message> localUidMap = new HashMap<String, Message>();
- for (Message message : localMessages) {
- localUidMap.put(message.getUid(), message);
- }
-
- Store remoteStore = Store.getInstance(account.getStoreUri(), mApplication);
- Folder remoteFolder = remoteStore.getFolder(folder);
-
- /*
- * If the folder is a "special" folder we need to see if it exists
- * on the remote server. It if does not exist we'll try to create it. If we
- * can't create we'll abort. This will happen on every single Pop3 folder as
- * designed and on Imap folders during error conditions. This allows us
- * to treat Pop3 and Imap the same in this code.
- */
- if (folder.equals(account.getTrashFolderName()) ||
- folder.equals(account.getSentFolderName()) ||
- folder.equals(account.getDraftsFolderName())) {
- if (!remoteFolder.exists()) {
- if (!remoteFolder.create(FolderType.HOLDS_MESSAGES)) {
- for (MessagingListener l : mListeners) {
- l.synchronizeMailboxFinished(account, folder, 0, 0);
- }
- return;
- }
- }
- }
-
- /*
- * Synchronization process:
- Open the folder
- Upload any local messages that are marked as PENDING_UPLOAD (Drafts, Sent, Trash)
- Get the message count
- Get the list of the newest Email.DEFAULT_VISIBLE_LIMIT messages
- getMessages(messageCount - Email.DEFAULT_VISIBLE_LIMIT, messageCount)
- See if we have each message locally, if not fetch it's flags and envelope
- Get and update the unread count for the folder
- Update the remote flags of any messages we have locally with an internal date
- newer than the remote message.
- Get the current flags for any messages we have locally but did not just download
- Update local flags
- For any message we have locally but not remotely, delete the local message to keep
- cache clean.
- Download larger parts of any new messages.
- (Optional) Download small attachments in the background.
- */
-
- /*
- * Open the remote folder. This pre-loads certain metadata like message count.
- */
- remoteFolder.open(OpenMode.READ_WRITE);
-
- /*
- * Trash any remote messages that are marked as trashed locally.
- */
-
- /*
- * Get the remote message count.
- */
- int remoteMessageCount = remoteFolder.getMessageCount();
-
- int visibleLimit = localFolder.getVisibleLimit();
-
- Message[] remoteMessages = new Message[0];
- final ArrayList<Message> unsyncedMessages = new ArrayList<Message>();
- HashMap<String, Message> remoteUidMap = new HashMap<String, Message>();
-
- if (remoteMessageCount > 0) {
- /*
- * Message numbers start at 1.
- */
- int remoteStart = Math.max(0, remoteMessageCount - visibleLimit) + 1;
- int remoteEnd = remoteMessageCount;
- remoteMessages = remoteFolder.getMessages(remoteStart, remoteEnd, null);
- for (Message message : remoteMessages) {
- remoteUidMap.put(message.getUid(), message);
- }
-
- /*
- * Get a list of the messages that are in the remote list but not on the
- * local store, or messages that are in the local store but failed to download
- * on the last sync. These are the new messages that we will download.
- */
- for (Message message : remoteMessages) {
- Message localMessage = localUidMap.get(message.getUid());
- if (localMessage == null ||
- (!localMessage.isSet(Flag.X_DOWNLOADED_FULL) &&
- !localMessage.isSet(Flag.X_DOWNLOADED_PARTIAL))) {
- unsyncedMessages.add(message);
- }
- }
- }
-
- /*
- * A list of messages that were downloaded and which did not have the Seen flag set.
- * This will serve to indicate the true "new" message count that will be reported to
- * the user via notification.
- */
- final ArrayList<Message> newMessages = new ArrayList<Message>();
-
- /*
- * Fetch the flags and envelope only of the new messages. This is intended to get us
- * critical data as fast as possible, and then we'll fill in the details.
- */
- if (unsyncedMessages.size() > 0) {
-
- /*
- * Reverse the order of the messages. Depending on the server this may get us
- * fetch results for newest to oldest. If not, no harm done.
- */
- Collections.reverse(unsyncedMessages);
-
- FetchProfile fp = new FetchProfile();
- fp.add(FetchProfile.Item.FLAGS);
- fp.add(FetchProfile.Item.ENVELOPE);
- remoteFolder.fetch(unsyncedMessages.toArray(new Message[0]), fp,
- new MessageRetrievalListener() {
- public void messageFinished(Message message, int number, int ofTotal) {
- try {
- // Store the new message locally
- localFolder.appendMessages(new Message[] {
- message
- });
-
- // And include it in the view
- if (message.getSubject() != null &&
- message.getFrom() != null) {
- /*
- * We check to make sure that we got something worth
- * showing (subject and from) because some protocols
- * (POP) may not be able to give us headers for
- * ENVELOPE, only size.
- */
- for (MessagingListener l : mListeners) {
- l.synchronizeMailboxNewMessage(account, folder,
- localFolder.getMessage(message.getUid()));
- }
- }
-
- if (!message.isSet(Flag.SEEN)) {
- newMessages.add(message);
- }
- }
- catch (Exception e) {
- Log.e(Email.LOG_TAG,
- "Error while storing downloaded message.",
- e);
- }
- }
-
- public void messageStarted(String uid, int number, int ofTotal) {
- }
- });
- }
-
- /*
- * Refresh the flags for any messages in the local store that we didn't just
- * download.
- */
- FetchProfile fp = new FetchProfile();
- fp.add(FetchProfile.Item.FLAGS);
- remoteFolder.fetch(remoteMessages, fp, null);
- for (Message remoteMessage : remoteMessages) {
- Message localMessage = localFolder.getMessage(remoteMessage.getUid());
- if (localMessage == null) {
- continue;
- }
- if (remoteMessage.isSet(Flag.SEEN) != localMessage.isSet(Flag.SEEN)) {
- localMessage.setFlag(Flag.SEEN, remoteMessage.isSet(Flag.SEEN));
- for (MessagingListener l : mListeners) {
- l.synchronizeMailboxNewMessage(account, folder, localMessage);
- }
- }
- }
-
- /*
- * Get and store the unread message count.
- */
- int remoteUnreadMessageCount = remoteFolder.getUnreadMessageCount();
- if (remoteUnreadMessageCount == -1) {
- localFolder.setUnreadMessageCount(localFolder.getUnreadMessageCount()
- + newMessages.size());
- }
- else {
- localFolder.setUnreadMessageCount(remoteUnreadMessageCount);
- }
-
- /*
- * Remove any messages that are in the local store but no longer on the remote store.
- */
- for (Message localMessage : localMessages) {
- if (remoteUidMap.get(localMessage.getUid()) == null) {
- localMessage.setFlag(Flag.X_DESTROYED, true);
- for (MessagingListener l : mListeners) {
- l.synchronizeMailboxRemovedMessage(account, folder, localMessage);
- }
- }
- }
-
- /*
- * Now we download the actual content of messages.
- */
- ArrayList<Message> largeMessages = new ArrayList<Message>();
- ArrayList<Message> smallMessages = new ArrayList<Message>();
- for (Message message : unsyncedMessages) {
- /*
- * Sort the messages into two buckets, small and large. Small messages will be
- * downloaded fully and large messages will be downloaded in parts. By sorting
- * into two buckets we can pipeline the commands for each set of messages
- * into a single command to the server saving lots of round trips.
- */
- if (message.getSize() > (MAX_SMALL_MESSAGE_SIZE)) {
- largeMessages.add(message);
- } else {
- smallMessages.add(message);
- }
- }
- /*
- * Grab the content of the small messages first. This is going to
- * be very fast and at very worst will be a single up of a few bytes and a single
- * download of 625k.
- */
- fp = new FetchProfile();
- fp.add(FetchProfile.Item.BODY);
- remoteFolder.fetch(smallMessages.toArray(new Message[smallMessages.size()]),
- fp, new MessageRetrievalListener() {
- public void messageFinished(Message message, int number, int ofTotal) {
- try {
- // Store the updated message locally
- localFolder.appendMessages(new Message[] {
- message
- });
-
- Message localMessage = localFolder.getMessage(message.getUid());
-
- // Set a flag indicating this message has now be fully downloaded
- localMessage.setFlag(Flag.X_DOWNLOADED_FULL, true);
-
- // Update the listener with what we've found
- for (MessagingListener l : mListeners) {
- l.synchronizeMailboxNewMessage(
- account,
- folder,
- localMessage);
- }
- }
- catch (MessagingException me) {
-
- }
- }
-
- public void messageStarted(String uid, int number, int ofTotal) {
- }
- });
-
- /*
- * Now do the large messages that require more round trips.
- */
- fp.clear();
- fp.add(FetchProfile.Item.STRUCTURE);
- remoteFolder.fetch(largeMessages.toArray(new Message[largeMessages.size()]),
- fp, null);
- for (Message message : largeMessages) {
- if (message.getBody() == null) {
- /*
- * The provider was unable to get the structure of the message, so
- * we'll download a reasonable portion of the messge and mark it as
- * incomplete so the entire thing can be downloaded later if the user
- * wishes to download it.
- */
- fp.clear();
- fp.add(FetchProfile.Item.BODY_SANE);
- /*
- * TODO a good optimization here would be to make sure that all Stores set
- * the proper size after this fetch and compare the before and after size. If
- * they equal we can mark this SYNCHRONIZED instead of PARTIALLY_SYNCHRONIZED
- */
-
- remoteFolder.fetch(new Message[] { message }, fp, null);
- // Store the updated message locally
- localFolder.appendMessages(new Message[] {
- message
- });
-
- Message localMessage = localFolder.getMessage(message.getUid());
-
- // Set a flag indicating that the message has been partially downloaded and
- // is ready for view.
- localMessage.setFlag(Flag.X_DOWNLOADED_PARTIAL, true);
- } else {
- /*
- * We have a structure to deal with, from which
- * we can pull down the parts we want to actually store.
- * Build a list of parts we are interested in. Text parts will be downloaded
- * right now, attachments will be left for later.
- */
-
- ArrayList<Part> viewables = new ArrayList<Part>();
- ArrayList<Part> attachments = new ArrayList<Part>();
- MimeUtility.collectParts(message, viewables, attachments);
-
- /*
- * Now download the parts we're interested in storing.
- */
- for (Part part : viewables) {
- fp.clear();
- fp.add(part);
- // TODO what happens if the network connection dies? We've got partial
- // messages with incorrect status stored.
- remoteFolder.fetch(new Message[] { message }, fp, null);
- }
- // Store the updated message locally
- localFolder.appendMessages(new Message[] {
- message
- });
-
- Message localMessage = localFolder.getMessage(message.getUid());
-
- // Set a flag indicating this message has been fully downloaded and can be
- // viewed.
- localMessage.setFlag(Flag.X_DOWNLOADED_FULL, true);
- }
-
- // Update the listener with what we've found
- for (MessagingListener l : mListeners) {
- l.synchronizeMailboxNewMessage(
- account,
- folder,
- localFolder.getMessage(message.getUid()));
- }
- }
-
-
- /*
- * Notify listeners that we're finally done.
- */
- for (MessagingListener l : mListeners) {
- l.synchronizeMailboxFinished(
- account,
- folder,
- remoteFolder.getMessageCount(), newMessages.size());
- }
-
- remoteFolder.close(false);
- localFolder.close(false);
- }
- catch (Exception e) {
- if (Config.LOGV) {
- Log.v(Email.LOG_TAG, "synchronizeMailbox", e);
- }
- for (MessagingListener l : mListeners) {
- l.synchronizeMailboxFailed(
- account,
- folder,
- e);
- }
- }
- }
-
- private void queuePendingCommand(Account account, PendingCommand command) {
- try {
- LocalStore localStore = (LocalStore) Store.getInstance(
- account.getLocalStoreUri(),
- mApplication);
- localStore.addPendingCommand(command);
- }
- catch (Exception e) {
- throw new RuntimeException("Unable to enqueue pending command", e);
- }
- }
-
- private void processPendingCommands(final Account account) {
- put("processPendingCommands", null, new Runnable() {
- public void run() {
- try {
- processPendingCommandsSynchronous(account);
- }
- catch (MessagingException me) {
- if (Config.LOGV) {
- Log.v(Email.LOG_TAG, "processPendingCommands", me);
- }
- /*
- * Ignore any exceptions from the commands. Commands will be processed
- * on the next round.
- */
- }
- }
- });
- }
-
- private void processPendingCommandsSynchronous(Account account) throws MessagingException {
- LocalStore localStore = (LocalStore) Store.getInstance(
- account.getLocalStoreUri(),
- mApplication);
- ArrayList<PendingCommand> commands = localStore.getPendingCommands();
- for (PendingCommand command : commands) {
- /*
- * We specifically do not catch any exceptions here. If a command fails it is
- * most likely due to a server or IO error and it must be retried before any
- * other command processes. This maintains the order of the commands.
- */
- if (PENDING_COMMAND_APPEND.equals(command.command)) {
- processPendingAppend(command, account);
- }
- else if (PENDING_COMMAND_MARK_READ.equals(command.command)) {
- processPendingMarkRead(command, account);
- }
- else if (PENDING_COMMAND_TRASH.equals(command.command)) {
- processPendingTrash(command, account);
- }
- localStore.removePendingCommand(command);
- }
- }
-
- /**
- * Process a pending append message command. This command uploads a local message to the
- * server, first checking to be sure that the server message is not newer than
- * the local message. Once the local message is successfully processed it is deleted so
- * that the server message will be synchronized down without an additional copy being
- * created.
- * TODO update the local message UID instead of deleteing it
- *
- * @param command arguments = (String folder, String uid)
- * @param account
- * @throws MessagingException
- */
- private void processPendingAppend(PendingCommand command, Account account)
- throws MessagingException {
- String folder = command.arguments[0];
- String uid = command.arguments[1];
-
- LocalStore localStore = (LocalStore) Store.getInstance(
- account.getLocalStoreUri(),
- mApplication);
- LocalFolder localFolder = (LocalFolder) localStore.getFolder(folder);
- LocalMessage localMessage = (LocalMessage) localFolder.getMessage(uid);
-
- if (localMessage == null) {
- return;
- }
-
- Store remoteStore = Store.getInstance(account.getStoreUri(), mApplication);
- Folder remoteFolder = remoteStore.getFolder(folder);
- if (!remoteFolder.exists()) {
- if (!remoteFolder.create(FolderType.HOLDS_MESSAGES)) {
- return;
- }
- }
- remoteFolder.open(OpenMode.READ_WRITE);
- if (remoteFolder.getMode() != OpenMode.READ_WRITE) {
- return;
- }
-
- Message remoteMessage = null;
- if (!localMessage.getUid().startsWith("Local")
- && !localMessage.getUid().contains("-")) {
- remoteMessage = remoteFolder.getMessage(localMessage.getUid());
- }
-
- if (remoteMessage == null) {
- /*
- * If the message does not exist remotely we just upload it and then
- * update our local copy with the new uid.
- */
- FetchProfile fp = new FetchProfile();
- fp.add(FetchProfile.Item.BODY);
- localFolder.fetch(new Message[] { localMessage }, fp, null);
- String oldUid = localMessage.getUid();
- remoteFolder.appendMessages(new Message[] { localMessage });
- localFolder.changeUid(localMessage);
- for (MessagingListener l : mListeners) {
- l.messageUidChanged(account, folder, oldUid, localMessage.getUid());
- }
- }
- else {
- /*
- * If the remote message exists we need to determine which copy to keep.
- */
- /*
- * See if the remote message is newer than ours.
- */
- FetchProfile fp = new FetchProfile();
- fp.add(FetchProfile.Item.ENVELOPE);
- remoteFolder.fetch(new Message[] { remoteMessage }, fp, null);
- Date localDate = localMessage.getInternalDate();
- Date remoteDate = remoteMessage.getInternalDate();
- if (remoteDate.compareTo(localDate) > 0) {
- /*
- * If the remote message is newer than ours we'll just
- * delete ours and move on. A sync will get the server message
- * if we need to be able to see it.
- */
- localMessage.setFlag(Flag.DELETED, true);
- }
- else {
- /*
- * Otherwise we'll upload our message and then delete the remote message.
- */
- fp.clear();
- fp = new FetchProfile();
- fp.add(FetchProfile.Item.BODY);
- localFolder.fetch(new Message[] { localMessage }, fp, null);
- String oldUid = localMessage.getUid();
- remoteFolder.appendMessages(new Message[] { localMessage });
- localFolder.changeUid(localMessage);
- for (MessagingListener l : mListeners) {
- l.messageUidChanged(account, folder, oldUid, localMessage.getUid());
- }
- remoteMessage.setFlag(Flag.DELETED, true);
- }
- }
- }
-
- /**
- * Process a pending trash message command.
- *
- * @param command arguments = (String folder, String uid)
- * @param account
- * @throws MessagingException
- */
- private void processPendingTrash(PendingCommand command, Account account)
- throws MessagingException {
- String folder = command.arguments[0];
- String uid = command.arguments[1];
-
- Store remoteStore = Store.getInstance(account.getStoreUri(), mApplication);
- Folder remoteFolder = remoteStore.getFolder(folder);
- if (!remoteFolder.exists()) {
- return;
- }
- remoteFolder.open(OpenMode.READ_WRITE);
- if (remoteFolder.getMode() != OpenMode.READ_WRITE) {
- return;
- }
-
- Message remoteMessage = null;
- if (!uid.startsWith("Local")
- && !uid.contains("-")) {
- remoteMessage = remoteFolder.getMessage(uid);
- }
- if (remoteMessage == null) {
- return;
- }
-
- Folder remoteTrashFolder = remoteStore.getFolder(account.getTrashFolderName());
- /*
- * Attempt to copy the remote message to the remote trash folder.
- */
- if (!remoteTrashFolder.exists()) {
- /*
- * If the remote trash folder doesn't exist we try to create it.
- */
- remoteTrashFolder.create(FolderType.HOLDS_MESSAGES);
- }
-
- if (remoteTrashFolder.exists()) {
- remoteFolder.copyMessages(new Message[] { remoteMessage }, remoteTrashFolder);
- }
-
- remoteMessage.setFlag(Flag.DELETED, true);
- remoteFolder.expunge();
- }
-
- /**
- * Processes a pending mark read or unread command.
- *
- * @param command arguments = (String folder, String uid, boolean read)
- * @param account
- */
- private void processPendingMarkRead(PendingCommand command, Account account)
- throws MessagingException {
- String folder = command.arguments[0];
- String uid = command.arguments[1];
- boolean read = Boolean.parseBoolean(command.arguments[2]);
-
- Store remoteStore = Store.getInstance(account.getStoreUri(), mApplication);
- Folder remoteFolder = remoteStore.getFolder(folder);
- if (!remoteFolder.exists()) {
- return;
- }
- remoteFolder.open(OpenMode.READ_WRITE);
- if (remoteFolder.getMode() != OpenMode.READ_WRITE) {
- return;
- }
- Message remoteMessage = null;
- if (!uid.startsWith("Local")
- && !uid.contains("-")) {
- remoteMessage = remoteFolder.getMessage(uid);
- }
- if (remoteMessage == null) {
- return;
- }
- remoteMessage.setFlag(Flag.SEEN, read);
- }
-
- /**
- * Mark the message with the given account, folder and uid either Seen or not Seen.
- * @param account
- * @param folder
- * @param uid
- * @param seen
- */
- public void markMessageRead(
- final Account account,
- final String folder,
- final String uid,
- final boolean seen) {
- try {
- Store localStore = Store.getInstance(account.getLocalStoreUri(), mApplication);
- Folder localFolder = localStore.getFolder(folder);
- localFolder.open(OpenMode.READ_WRITE);
-
- Message message = localFolder.getMessage(uid);
- message.setFlag(Flag.SEEN, seen);
- PendingCommand command = new PendingCommand();
- command.command = PENDING_COMMAND_MARK_READ;
- command.arguments = new String[] { folder, uid, Boolean.toString(seen) };
- queuePendingCommand(account, command);
- processPendingCommands(account);
- }
- catch (MessagingException me) {
- throw new RuntimeException(me);
- }
- }
-
- private void loadMessageForViewRemote(final Account account, final String folder,
- final String uid, MessagingListener listener) {
- put("loadMessageForViewRemote", listener, new Runnable() {
- public void run() {
- try {
- Store localStore = Store.getInstance(account.getLocalStoreUri(), mApplication);
- LocalFolder localFolder = (LocalFolder) localStore.getFolder(folder);
- localFolder.open(OpenMode.READ_WRITE);
-
- Message message = localFolder.getMessage(uid);
-
- if (message.isSet(Flag.X_DOWNLOADED_FULL)) {
- /*
- * If the message has been synchronized since we were called we'll
- * just hand it back cause it's ready to go.
- */
- FetchProfile fp = new FetchProfile();
- fp.add(FetchProfile.Item.ENVELOPE);
- fp.add(FetchProfile.Item.BODY);
- localFolder.fetch(new Message[] { message }, fp, null);
-
- for (MessagingListener l : mListeners) {
- l.loadMessageForViewBodyAvailable(account, folder, uid, message);
- }
- for (MessagingListener l : mListeners) {
- l.loadMessageForViewFinished(account, folder, uid, message);
- }
- localFolder.close(false);
- return;
- }
-
- /*
- * At this point the message is not available, so we need to download it
- * fully if possible.
- */
-
- Store remoteStore = Store.getInstance(account.getStoreUri(), mApplication);
- Folder remoteFolder = remoteStore.getFolder(folder);
- remoteFolder.open(OpenMode.READ_WRITE);
-
- // Get the remote message and fully download it
- Message remoteMessage = remoteFolder.getMessage(uid);
- FetchProfile fp = new FetchProfile();
- fp.add(FetchProfile.Item.BODY);
- remoteFolder.fetch(new Message[] { remoteMessage }, fp, null);
-
- // Store the message locally and load the stored message into memory
- localFolder.appendMessages(new Message[] { remoteMessage });
- message = localFolder.getMessage(uid);
- localFolder.fetch(new Message[] { message }, fp, null);
-
- // This is a view message request, so mark it read
- if (!message.isSet(Flag.SEEN)) {
- markMessageRead(account, folder, uid, true);
- }
-
- // Mark that this message is now fully synched
- message.setFlag(Flag.X_DOWNLOADED_FULL, true);
-
- for (MessagingListener l : mListeners) {
- l.loadMessageForViewBodyAvailable(account, folder, uid, message);
- }
- for (MessagingListener l : mListeners) {
- l.loadMessageForViewFinished(account, folder, uid, message);
- }
- remoteFolder.close(false);
- localFolder.close(false);
- }
- catch (Exception e) {
- for (MessagingListener l : mListeners) {
- l.loadMessageForViewFailed(account, folder, uid, e.getMessage());
- }
- }
- }
- });
- }
-
- public void loadMessageForView(final Account account, final String folder, final String uid,
- MessagingListener listener) {
- for (MessagingListener l : mListeners) {
- l.loadMessageForViewStarted(account, folder, uid);
- }
- try {
- Store localStore = Store.getInstance(account.getLocalStoreUri(), mApplication);
- LocalFolder localFolder = (LocalFolder) localStore.getFolder(folder);
- localFolder.open(OpenMode.READ_WRITE);
-
- Message message = localFolder.getMessage(uid);
-
- for (MessagingListener l : mListeners) {
- l.loadMessageForViewHeadersAvailable(account, folder, uid, message);
- }
-
- if (!message.isSet(Flag.X_DOWNLOADED_FULL)) {
- loadMessageForViewRemote(account, folder, uid, listener);
- localFolder.close(false);
- return;
- }
-
- if (!message.isSet(Flag.SEEN)) {
- markMessageRead(account, folder, uid, true);
- }
-
- FetchProfile fp = new FetchProfile();
- fp.add(FetchProfile.Item.ENVELOPE);
- fp.add(FetchProfile.Item.BODY);
- localFolder.fetch(new Message[] {
- message
- }, fp, null);
-
- for (MessagingListener l : mListeners) {
- l.loadMessageForViewBodyAvailable(account, folder, uid, message);
- }
-
- for (MessagingListener l : mListeners) {
- l.loadMessageForViewFinished(account, folder, uid, message);
- }
- localFolder.close(false);
- }
- catch (Exception e) {
- for (MessagingListener l : mListeners) {
- l.loadMessageForViewFailed(account, folder, uid, e.getMessage());
- }
- }
- }
-
- /**
- * Attempts to load the attachment specified by part from the given account and message.
- * @param account
- * @param message
- * @param part
- * @param listener
- */
- public void loadAttachment(
- final Account account,
- final Message message,
- final Part part,
- final Object tag,
- MessagingListener listener) {
- /*
- * Check if the attachment has already been downloaded. If it has there's no reason to
- * download it, so we just tell the listener that it's ready to go.
- */
- try {
- if (part.getBody() != null) {
- for (MessagingListener l : mListeners) {
- l.loadAttachmentStarted(account, message, part, tag, false);
- }
-
- for (MessagingListener l : mListeners) {
- l.loadAttachmentFinished(account, message, part, tag);
- }
- return;
- }
- }
- catch (MessagingException me) {
- /*
- * If the header isn't there the attachment isn't downloaded yet, so just continue
- * on.
- */
- }
-
- for (MessagingListener l : mListeners) {
- l.loadAttachmentStarted(account, message, part, tag, true);
- }
-
- put("loadAttachment", listener, new Runnable() {
- public void run() {
- try {
- LocalStore localStore =
- (LocalStore) Store.getInstance(account.getLocalStoreUri(), mApplication);
- /*
- * We clear out any attachments already cached in the entire store and then
- * we update the passed in message to reflect that there are no cached
- * attachments. This is in support of limiting the account to having one
- * attachment downloaded at a time.
- */
- localStore.pruneCachedAttachments();
- ArrayList<Part> viewables = new ArrayList<Part>();
- ArrayList<Part> attachments = new ArrayList<Part>();
- MimeUtility.collectParts(message, viewables, attachments);
- for (Part attachment : attachments) {
- attachment.setBody(null);
- }
- Store remoteStore = Store.getInstance(account.getStoreUri(), mApplication);
- LocalFolder localFolder =
- (LocalFolder) localStore.getFolder(message.getFolder().getName());
- Folder remoteFolder = remoteStore.getFolder(message.getFolder().getName());
- remoteFolder.open(OpenMode.READ_WRITE);
-
- FetchProfile fp = new FetchProfile();
- fp.add(part);
- remoteFolder.fetch(new Message[] { message }, fp, null);
- localFolder.updateMessage((LocalMessage)message);
- localFolder.close(false);
- for (MessagingListener l : mListeners) {
- l.loadAttachmentFinished(account, message, part, tag);
- }
- }
- catch (MessagingException me) {
- if (Config.LOGV) {
- Log.v(Email.LOG_TAG, "", me);
- }
- for (MessagingListener l : mListeners) {
- l.loadAttachmentFailed(account, message, part, tag, me.getMessage());
- }
- }
- }
- });
- }
-
- /**
- * Stores the given message in the Outbox and starts a sendPendingMessages command to
- * attempt to send the message.
- * @param account
- * @param message
- * @param listener
- */
- public void sendMessage(final Account account,
- final Message message,
- MessagingListener listener) {
- try {
- Store localStore = Store.getInstance(account.getLocalStoreUri(), mApplication);
- LocalFolder localFolder =
- (LocalFolder) localStore.getFolder(account.getOutboxFolderName());
- localFolder.open(OpenMode.READ_WRITE);
- localFolder.appendMessages(new Message[] {
- message
- });
- Message localMessage = localFolder.getMessage(message.getUid());
- localMessage.setFlag(Flag.X_DOWNLOADED_FULL, true);
- localFolder.close(false);
- sendPendingMessages(account, null);
- }
- catch (Exception e) {
- for (MessagingListener l : mListeners) {
- // TODO general failed
- }
- }
- }
-
- /**
- * Attempt to send any messages that are sitting in the Outbox.
- * @param account
- * @param listener
- */
- public void sendPendingMessages(final Account account,
- MessagingListener listener) {
- put("sendPendingMessages", listener, new Runnable() {
- public void run() {
- sendPendingMessagesSynchronous(account);
- }
- });
- }
-
- /**
- * Attempt to send any messages that are sitting in the Outbox.
- * @param account
- * @param listener
- */
- public void sendPendingMessagesSynchronous(final Account account) {
- try {
- Store localStore = Store.getInstance(
- account.getLocalStoreUri(),
- mApplication);
- Folder localFolder = localStore.getFolder(
- account.getOutboxFolderName());
- if (!localFolder.exists()) {
- return;
- }
- localFolder.open(OpenMode.READ_WRITE);
-
- Message[] localMessages = localFolder.getMessages(null);
-
- /*
- * The profile we will use to pull all of the content
- * for a given local message into memory for sending.
- */
- FetchProfile fp = new FetchProfile();
- fp.add(FetchProfile.Item.ENVELOPE);
- fp.add(FetchProfile.Item.BODY);
-
- LocalFolder localSentFolder =
- (LocalFolder) localStore.getFolder(
- account.getSentFolderName());
-
- Sender sender = Sender.getInstance(account.getSenderUri());
- for (Message message : localMessages) {
- try {
- localFolder.fetch(new Message[] { message }, fp, null);
- try {
- message.setFlag(Flag.X_SEND_IN_PROGRESS, true);
- sender.sendMessage(message);
- message.setFlag(Flag.X_SEND_IN_PROGRESS, false);
- localFolder.copyMessages(
- new Message[] { message },
- localSentFolder);
-
- PendingCommand command = new PendingCommand();
- command.command = PENDING_COMMAND_APPEND;
- command.arguments =
- new String[] {
- localSentFolder.getName(),
- message.getUid() };
- queuePendingCommand(account, command);
- processPendingCommands(account);
- message.setFlag(Flag.X_DESTROYED, true);
- }
- catch (Exception e) {
- message.setFlag(Flag.X_SEND_FAILED, true);
- }
- }
- catch (Exception e) {
- /*
- * We ignore this exception because a future refresh will retry this
- * message.
- */
- }
- }
- localFolder.expunge();
- if (localFolder.getMessageCount() == 0) {
- localFolder.delete(false);
- }
- for (MessagingListener l : mListeners) {
- l.sendPendingMessagesCompleted(account);
- }
- }
- catch (Exception e) {
- for (MessagingListener l : mListeners) {
- // TODO general failed
- }
- }
- }
-
- /**
- * We do the local portion of this synchronously because other activities may have to make
- * updates based on what happens here
- * @param account
- * @param folder
- * @param message
- * @param listener
- */
- public void deleteMessage(final Account account, final String folder, final Message message,
- MessagingListener listener) {
- if (folder.equals(account.getTrashFolderName())) {
- return;
- }
- try {
- Store localStore = Store.getInstance(account.getLocalStoreUri(), mApplication);
- Folder localFolder = localStore.getFolder(folder);
- Folder localTrashFolder = localStore.getFolder(account.getTrashFolderName());
-
- localFolder.copyMessages(new Message[] { message }, localTrashFolder);
- message.setFlag(Flag.DELETED, true);
-
- if (account.getDeletePolicy() == Account.DELETE_POLICY_ON_DELETE) {
- PendingCommand command = new PendingCommand();
- command.command = PENDING_COMMAND_TRASH;
- command.arguments = new String[] { folder, message.getUid() };
- queuePendingCommand(account, command);
- processPendingCommands(account);
- }
- }
- catch (MessagingException me) {
- throw new RuntimeException("Error deleting message from local store.", me);
- }
- }
-
- public void emptyTrash(final Account account, MessagingListener listener) {
- put("emptyTrash", listener, new Runnable() {
- public void run() {
- // TODO IMAP
- try {
- Store localStore = Store.getInstance(account.getLocalStoreUri(), mApplication);
- Folder localFolder = localStore.getFolder(account.getTrashFolderName());
- localFolder.open(OpenMode.READ_WRITE);
- Message[] messages = localFolder.getMessages(null);
- localFolder.setFlags(messages, new Flag[] {
- Flag.DELETED
- }, true);
- localFolder.close(true);
- for (MessagingListener l : mListeners) {
- l.emptyTrashCompleted(account);
- }
- }
- catch (Exception e) {
- // TODO
- if (Config.LOGV) {
- Log.v(Email.LOG_TAG, "emptyTrash");
- }
- }
- }
- });
- }
-
- /**
- * Checks mail for one or multiple accounts. If account is null all accounts
- * are checked.
- *
- * TODO: There is no use case for "check all accounts". Clean up this API to remove
- * that case. Callers can supply the appropriate list.
- *
- * @param context
- * @param accountsToCheck List of accounts to check, or null to check all accounts
- * @param listener
- */
- public void checkMail(final Context context, final Account[] accountsToCheck,
- final MessagingListener listener) {
- for (MessagingListener l : mListeners) {
- l.checkMailStarted(context, null); // TODO this needs to pass the actual array
- }
- put("checkMail", listener, new Runnable() {
- public void run() {
- Account[] accounts = accountsToCheck;
- if (accounts == null) {
- accounts = Preferences.getPreferences(context).getAccounts();
- }
- for (Account account : accounts) {
- sendPendingMessagesSynchronous(account);
- synchronizeMailboxSyncronous(account, Email.INBOX);
- }
- for (MessagingListener l : mListeners) {
- l.checkMailFinished(context, null); // TODO this needs to pass the actual array
- }
- }
- });
- }
-
- public void saveDraft(final Account account, final Message message) {
- try {
- Store localStore = Store.getInstance(account.getLocalStoreUri(), mApplication);
- LocalFolder localFolder =
- (LocalFolder) localStore.getFolder(account.getDraftsFolderName());
- localFolder.open(OpenMode.READ_WRITE);
- localFolder.appendMessages(new Message[] {
- message
- });
- Message localMessage = localFolder.getMessage(message.getUid());
- localMessage.setFlag(Flag.X_DOWNLOADED_FULL, true);
-
- PendingCommand command = new PendingCommand();
- command.command = PENDING_COMMAND_APPEND;
- command.arguments = new String[] {
- localFolder.getName(),
- localMessage.getUid() };
- queuePendingCommand(account, command);
- processPendingCommands(account);
- }
- catch (MessagingException e) {
- Log.e(Email.LOG_TAG, "Unable to save message as draft.", e);
- }
- }
-
- class Command {
- public Runnable runnable;
-
- public MessagingListener listener;
-
- public String description;
- }
-}
diff --git a/src/com/android/email/MessagingListener.java b/src/com/android/email/MessagingListener.java
deleted file mode 100644
index 44ddc4229..000000000
--- a/src/com/android/email/MessagingListener.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email;
-
-import android.content.Context;
-
-import com.android.email.mail.Folder;
-import com.android.email.mail.Message;
-import com.android.email.mail.Part;
-
-/**
- * Defines the interface that MessagingController will use to callback to requesters. This class
- * is defined as non-abstract so that someone who wants to receive only a few messages can
- * do so without implementing the entire interface. It is highly recommended that users of
- * this interface use the @Override annotation in their implementations to avoid being caught by
- * changes in this class.
- */
-public class MessagingListener {
- public void listFoldersStarted(Account account) {
- }
-
- public void listFolders(Account account, Folder[] folders) {
- }
-
- public void listFoldersFailed(Account account, String message) {
- }
-
- public void listFoldersFinished(Account account) {
- }
-
- public void listLocalMessagesStarted(Account account, String folder) {
- }
-
- public void listLocalMessages(Account account, String folder, Message[] messages) {
- }
-
- public void listLocalMessagesFailed(Account account, String folder, String message) {
- }
-
- public void listLocalMessagesFinished(Account account, String folder) {
- }
-
- public void synchronizeMailboxStarted(Account account, String folder) {
- }
-
- public void synchronizeMailboxNewMessage(Account account, String folder, Message message) {
- }
-
- public void synchronizeMailboxRemovedMessage(Account account, String folder,Message message) {
- }
-
- public void synchronizeMailboxFinished(Account account, String folder,
- int totalMessagesInMailbox, int numNewMessages) {
- }
-
- public void synchronizeMailboxFailed(Account account, String folder, Exception e) {
- }
-
- public void loadMessageForViewStarted(Account account, String folder, String uid) {
- }
-
- public void loadMessageForViewHeadersAvailable(Account account, String folder, String uid,
- Message message) {
- }
-
- public void loadMessageForViewBodyAvailable(Account account, String folder, String uid,
- Message message) {
- }
-
- public void loadMessageForViewFinished(Account account, String folder, String uid,
- Message message) {
- }
-
- public void loadMessageForViewFailed(Account account, String folder, String uid, String message) {
- }
-
- public void checkMailStarted(Context context, Account account) {
- }
-
- public void checkMailFinished(Context context, Account account) {
- }
-
- public void checkMailFailed(Context context, Account account, String reason) {
- }
-
- public void sendPendingMessagesCompleted(Account account) {
- }
-
- public void emptyTrashCompleted(Account account) {
- }
-
- public void messageUidChanged(Account account, String folder, String oldUid, String newUid) {
-
- }
-
- public void loadAttachmentStarted(
- Account account,
- Message message,
- Part part,
- Object tag,
- boolean requiresDownload)
- {
- }
-
- public void loadAttachmentFinished(
- Account account,
- Message message,
- Part part,
- Object tag)
- {
- }
-
- public void loadAttachmentFailed(
- Account account,
- Message message,
- Part part,
- Object tag,
- String reason)
- {
- }
-
- /**
- * General notification messages subclasses can override to be notified that the controller
- * has completed a command. This is useful for turning off progress indicators that may have
- * been left over from previous commands.
- * @param moreCommandsToRun True if the controller will continue on to another command
- * immediately.
- */
- public void controllerCommandCompleted(boolean moreCommandsToRun) {
-
- }
-}
diff --git a/src/com/android/email/PeekableInputStream.java b/src/com/android/email/PeekableInputStream.java
deleted file mode 100644
index cef54f90e..000000000
--- a/src/com/android/email/PeekableInputStream.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * A filtering InputStream that allows single byte "peeks" without consuming the byte. The
- * client of this stream can call peek() to see the next available byte in the stream
- * and a subsequent read will still return the peeked byte.
- */
-public class PeekableInputStream extends InputStream {
- private InputStream mIn;
- private boolean mPeeked;
- private int mPeekedByte;
-
- public PeekableInputStream(InputStream in) {
- this.mIn = in;
- }
-
- @Override
- public int read() throws IOException {
- if (!mPeeked) {
- return mIn.read();
- } else {
- mPeeked = false;
- return mPeekedByte;
- }
- }
-
- public int peek() throws IOException {
- if (!mPeeked) {
- mPeekedByte = read();
- mPeeked = true;
- }
- return mPeekedByte;
- }
-
- @Override
- public int read(byte[] b, int offset, int length) throws IOException {
- if (!mPeeked) {
- return mIn.read(b, offset, length);
- } else {
- b[0] = (byte)mPeekedByte;
- mPeeked = false;
- int r = mIn.read(b, offset + 1, length - 1);
- if (r == -1) {
- return 1;
- } else {
- return r + 1;
- }
- }
- }
-
- @Override
- public int read(byte[] b) throws IOException {
- return read(b, 0, b.length);
- }
-
- public String toString() {
- return String.format("PeekableInputStream(in=%s, peeked=%b, peekedByte=%d)",
- mIn.toString(), mPeeked, mPeekedByte);
- }
-}
diff --git a/src/com/android/email/Preferences.java b/src/com/android/email/Preferences.java
deleted file mode 100644
index e2611ee65..000000000
--- a/src/com/android/email/Preferences.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email;
-
-import java.util.Arrays;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.net.Uri;
-import android.util.Config;
-import android.util.Log;
-
-public class Preferences {
- private static Preferences preferences;
-
- SharedPreferences mSharedPreferences;
-
- private Preferences(Context context) {
- mSharedPreferences = context.getSharedPreferences("AndroidMail.Main", Context.MODE_PRIVATE);
- }
-
- /**
- * TODO need to think about what happens if this gets GCed along with the
- * Activity that initialized it. Do we lose ability to read Preferences in
- * further Activities? Maybe this should be stored in the Application
- * context.
- *
- * @return
- */
- public static synchronized Preferences getPreferences(Context context) {
- if (preferences == null) {
- preferences = new Preferences(context);
- }
- return preferences;
- }
-
- /**
- * Returns an array of the accounts on the system. If no accounts are
- * registered the method returns an empty array.
- *
- * @return
- */
- public Account[] getAccounts() {
- String accountUuids = mSharedPreferences.getString("accountUuids", null);
- if (accountUuids == null || accountUuids.length() == 0) {
- return new Account[] {};
- }
- String[] uuids = accountUuids.split(",");
- Account[] accounts = new Account[uuids.length];
- for (int i = 0, length = uuids.length; i < length; i++) {
- accounts[i] = new Account(this, uuids[i]);
- }
- return accounts;
- }
-
- /**
- * Get an account object by Uri, or return null if no account exists
- * TODO: Merge hardcoded strings with the same strings in Account.java
- */
- public Account getAccountByContentUri(Uri uri) {
- if (!"content".equals(uri.getScheme()) || !"accounts".equals(uri.getAuthority())) {
- return null;
- }
- String uuid = uri.getPath().substring(1);
- if (uuid == null) {
- return null;
- }
- String accountUuids = mSharedPreferences.getString("accountUuids", null);
- if (accountUuids == null || accountUuids.length() == 0) {
- return null;
- }
- String[] uuids = accountUuids.split(",");
- for (int i = 0, length = uuids.length; i < length; i++) {
- if (uuid.equals(uuids[i])) {
- return new Account(this, uuid);
- }
- }
- return null;
- }
-
- /**
- * Returns the Account marked as default. If no account is marked as default
- * the first account in the list is marked as default and then returned. If
- * there are no accounts on the system the method returns null.
- *
- * @return
- */
- public Account getDefaultAccount() {
- String defaultAccountUuid = mSharedPreferences.getString("defaultAccountUuid", null);
- Account defaultAccount = null;
- Account[] accounts = getAccounts();
- if (defaultAccountUuid != null) {
- for (Account account : accounts) {
- if (account.getUuid().equals(defaultAccountUuid)) {
- defaultAccount = account;
- break;
- }
- }
- }
-
- if (defaultAccount == null) {
- if (accounts.length > 0) {
- defaultAccount = accounts[0];
- setDefaultAccount(defaultAccount);
- }
- }
-
- return defaultAccount;
- }
-
- public void setDefaultAccount(Account account) {
- mSharedPreferences.edit().putString("defaultAccountUuid", account.getUuid()).commit();
- }
-
- public void setEnableDebugLogging(boolean value) {
- mSharedPreferences.edit().putBoolean("enableDebugLogging", value).commit();
- }
-
- public boolean geteEnableDebugLogging() {
- return mSharedPreferences.getBoolean("enableDebugLogging", false);
- }
-
- public void setEnableSensitiveLogging(boolean value) {
- mSharedPreferences.edit().putBoolean("enableSensitiveLogging", value).commit();
- }
-
- public boolean getEnableSensitiveLogging() {
- return mSharedPreferences.getBoolean("enableSensitiveLogging", false);
- }
-
- public void save() {
- }
-
- public void clear() {
- mSharedPreferences.edit().clear().commit();
- }
-
- public void dump() {
- if (Config.LOGV) {
- for (String key : mSharedPreferences.getAll().keySet()) {
- Log.v(Email.LOG_TAG, key + " = " + mSharedPreferences.getAll().get(key));
- }
- }
- }
-}
diff --git a/src/com/android/email/Utility.java b/src/com/android/email/Utility.java
deleted file mode 100644
index ede1a0651..000000000
--- a/src/com/android/email/Utility.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
-import java.util.Date;
-
-import com.android.email.codec.binary.Base64;
-
-import android.text.Editable;
-import android.widget.TextView;
-
-public class Utility {
- public final static String readInputStream(InputStream in, String encoding) throws IOException {
- InputStreamReader reader = new InputStreamReader(in, encoding);
- StringBuffer sb = new StringBuffer();
- int count;
- char[] buf = new char[512];
- while ((count = reader.read(buf)) != -1) {
- sb.append(buf, 0, count);
- }
- return sb.toString();
- }
-
- public final static boolean arrayContains(Object[] a, Object o) {
- for (int i = 0, count = a.length; i < count; i++) {
- if (a[i].equals(o)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Combines the given array of Objects into a single string using the
- * seperator character and each Object's toString() method. between each
- * part.
- *
- * @param parts
- * @param seperator
- * @return
- */
- public static String combine(Object[] parts, char seperator) {
- if (parts == null) {
- return null;
- }
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < parts.length; i++) {
- sb.append(parts[i].toString());
- if (i < parts.length - 1) {
- sb.append(seperator);
- }
- }
- return sb.toString();
- }
-
- public static String base64Decode(String encoded) {
- if (encoded == null) {
- return null;
- }
- byte[] decoded = new Base64().decode(encoded.getBytes());
- return new String(decoded);
- }
-
- public static String base64Encode(String s) {
- if (s == null) {
- return s;
- }
- byte[] encoded = new Base64().encode(s.getBytes());
- return new String(encoded);
- }
-
- public static boolean requiredFieldValid(TextView view) {
- return view.getText() != null && view.getText().length() > 0;
- }
-
- public static boolean requiredFieldValid(Editable s) {
- return s != null && s.length() > 0;
- }
-
- /**
- * Ensures that the given string starts and ends with the double quote character. The string is not modified in any way except to add the
- * double quote character to start and end if it's not already there.
- *
- * TODO: Rename this, because "quoteString()" can mean so many different things.
- *
- * sample -> "sample"
- * "sample" -> "sample"
- * ""sample"" -> "sample"
- * "sample"" -> "sample"
- * sa"mp"le -> "sa"mp"le"
- * "sa"mp"le" -> "sa"mp"le"
- * (empty string) -> ""
- * " -> ""
- * @param s
- * @return
- */
- public static String quoteString(String s) {
- if (s == null) {
- return null;
- }
- if (!s.matches("^\".*\"$")) {
- return "\"" + s + "\"";
- }
- else {
- return s;
- }
- }
-
- /**
- * Apply quoting rules per IMAP RFC,
- * quoted = DQUOTE *QUOTED-CHAR DQUOTE
- * QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> / "\" quoted-specials
- * quoted-specials = DQUOTE / "\"
- *
- * This is used primarily for IMAP login, but might be useful elsewhere.
- *
- * NOTE: Not very efficient - you may wish to preflight this, or perhaps it should check
- * for trouble chars before calling the replace functions.
- *
- * @param s The string to be quoted.
- * @return A copy of the string, having undergone quoting as described above
- */
- public static String imapQuoted(String s) {
-
- // First, quote any backslashes by replacing \ with \\
- // regex Pattern: \\ (Java string const = \\\\)
- // Substitute: \\\\ (Java string const = \\\\\\\\)
- String result = s.replaceAll("\\\\", "\\\\\\\\");
-
- // Then, quote any double-quotes by replacing " with \"
- // regex Pattern: " (Java string const = \")
- // Substitute: \\" (Java string const = \\\\\")
- result = result.replaceAll("\"", "\\\\\"");
-
- // return string with quotes around it
- return "\"" + result + "\"";
- }
-
- /**
- * A fast version of URLDecoder.decode() that works only with UTF-8 and does only two
- * allocations. This version is around 3x as fast as the standard one and I'm using it
- * hundreds of times in places that slow down the UI, so it helps.
- */
- public static String fastUrlDecode(String s) {
- try {
- byte[] bytes = s.getBytes("UTF-8");
- byte ch;
- int length = 0;
- for (int i = 0, count = bytes.length; i < count; i++) {
- ch = bytes[i];
- if (ch == '%') {
- int h = (bytes[i + 1] - '0');
- int l = (bytes[i + 2] - '0');
- if (h > 9) {
- h -= 7;
- }
- if (l > 9) {
- l -= 7;
- }
- bytes[length] = (byte) ((h << 4) | l);
- i += 2;
- }
- else if (ch == '+') {
- bytes[length] = ' ';
- }
- else {
- bytes[length] = bytes[i];
- }
- length++;
- }
- return new String(bytes, 0, length, "UTF-8");
- }
- catch (UnsupportedEncodingException uee) {
- return null;
- }
- }
-
- /**
- * Returns true if the specified date is within today. Returns false otherwise.
- * @param date
- * @return
- */
- public static boolean isDateToday(Date date) {
- // TODO But Calendar is so slowwwwwww....
- Date today = new Date();
- if (date.getYear() == today.getYear() &&
- date.getMonth() == today.getMonth() &&
- date.getDate() == today.getDate()) {
- return true;
- }
- return false;
- }
-
- /*
- * TODO disabled this method globally. It is used in all the settings screens but I just
- * noticed that an unrelated icon was dimmed. Android must share drawables internally.
- */
- public static void setCompoundDrawablesAlpha(TextView view, int alpha) {
-// Drawable[] drawables = view.getCompoundDrawables();
-// for (Drawable drawable : drawables) {
-// if (drawable != null) {
-// drawable.setAlpha(alpha);
-// }
-// }
- }
-}
diff --git a/src/com/android/email/activity/AccountShortcutPicker.java b/src/com/android/email/activity/AccountShortcutPicker.java
deleted file mode 100644
index 554b69076..000000000
--- a/src/com/android/email/activity/AccountShortcutPicker.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity;
-
-import com.android.email.Account;
-import com.android.email.Email;
-import com.android.email.Preferences;
-import com.android.email.R;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Store;
-import com.android.email.mail.store.LocalStore;
-import com.android.email.mail.store.LocalStore.LocalFolder;
-
-import android.app.ListActivity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-import android.widget.TextView;
-import android.widget.AdapterView.OnItemClickListener;
-
-/**
- *
- * This class implements a launcher shortcut for directly accessing a single account.
- *
- * This is simply a lightweight version of Accounts, and should almost certainly be merged with it
- * (or, one could be a base class of the other).
- */
-public class AccountShortcutPicker extends ListActivity implements OnItemClickListener {
-
- Account[] mAccounts;
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- // finish() immediately if we aren't supposed to be here
- if (!Intent.ACTION_CREATE_SHORTCUT.equals(getIntent().getAction())) {
- finish();
- return;
- }
-
- // finish() immediately if no accounts are configured
- mAccounts = Preferences.getPreferences(this).getAccounts();
- if (mAccounts.length == 0) {
- finish();
- return;
- }
-
- setContentView(R.layout.accounts);
- ListView listView = getListView();
- listView.setOnItemClickListener(this);
- listView.setItemsCanFocus(false);
- listView.setEmptyView(findViewById(R.id.empty));
- }
-
- @Override
- public void onResume() {
- super.onResume();
- refresh();
- }
-
- private void refresh() {
- getListView().setAdapter(new AccountsAdapter(mAccounts));
- }
-
- private void onOpenAccount(Account account) {
- // generate & return intents
- setupShortcut(account);
- finish();
- }
-
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- Account account = (Account)parent.getItemAtPosition(position);
- onOpenAccount(account);
- }
-
- class AccountsAdapter extends ArrayAdapter<Account> {
- public AccountsAdapter(Account[] accounts) {
- super(AccountShortcutPicker.this, 0, accounts);
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Account account = getItem(position);
- View view;
- if (convertView != null) {
- view = convertView;
- }
- else {
- view = getLayoutInflater().inflate(R.layout.accounts_item, parent, false);
- }
- AccountViewHolder holder = (AccountViewHolder) view.getTag();
- if (holder == null) {
- holder = new AccountViewHolder();
- holder.description = (TextView) view.findViewById(R.id.description);
- holder.email = (TextView) view.findViewById(R.id.email);
- holder.newMessageCount = (TextView) view.findViewById(R.id.new_message_count);
- view.setTag(holder);
- }
- holder.description.setText(account.getDescription());
- holder.email.setText(account.getEmail());
- if (account.getEmail().equals(account.getDescription())) {
- holder.email.setVisibility(View.GONE);
- }
- int unreadMessageCount = 0;
- try {
- LocalStore localStore = (LocalStore) Store.getInstance(
- account.getLocalStoreUri(),
- getApplication());
- LocalFolder localFolder = (LocalFolder) localStore.getFolder(Email.INBOX);
- if (localFolder.exists()) {
- unreadMessageCount = localFolder.getUnreadMessageCount();
- }
- }
- catch (MessagingException me) {
- /*
- * This is not expected to fail under normal circumstances.
- */
- throw new RuntimeException("Unable to get unread count from local store.", me);
- }
- holder.newMessageCount.setText(Integer.toString(unreadMessageCount));
- holder.newMessageCount.setVisibility(unreadMessageCount > 0 ? View.VISIBLE : View.GONE);
- return view;
- }
-
- class AccountViewHolder {
- public TextView description;
- public TextView email;
- public TextView newMessageCount;
- }
- }
-
- /**
- * This function creates a shortcut and returns it to the caller. There are actually two
- * intents that you will send back.
- *
- * The first intent serves as a container for the shortcut and is returned to the launcher by
- * setResult(). This intent must contain three fields:
- *
- * <ul>
- * <li>{@link android.content.Intent#EXTRA_SHORTCUT_INTENT} The shortcut intent.</li>
- * <li>{@link android.content.Intent#EXTRA_SHORTCUT_NAME} The text that will be displayed with
- * the shortcut.</li>
- * <li>{@link android.content.Intent#EXTRA_SHORTCUT_ICON} The shortcut's icon, if provided as a
- * bitmap, <i>or</i> {@link android.content.Intent#EXTRA_SHORTCUT_ICON_RESOURCE} if provided as
- * a drawable resource.</li>
- * </ul>
- *
- * If you use a simple drawable resource, note that you must wrapper it using
- * {@link android.content.Intent.ShortcutIconResource}, as shown below. This is required so
- * that the launcher can access resources that are stored in your application's .apk file. If
- * you return a bitmap, such as a thumbnail, you can simply put the bitmap into the extras
- * bundle using {@link android.content.Intent#EXTRA_SHORTCUT_ICON}.
- *
- * The shortcut intent can be any intent that you wish the launcher to send, when the user
- * clicks on the shortcut. Typically this will be {@link android.content.Intent#ACTION_VIEW}
- * with an appropriate Uri for your content, but any Intent will work here as long as it
- * triggers the desired action within your Activity.
- */
- private void setupShortcut(Account account) {
- // First, set up the shortcut intent.
-
- Intent shortcutIntent = FolderMessageList.actionHandleAccountUriIntent(this,
- account, Email.INBOX);
-
- // Then, set up the container intent (the response to the caller)
-
- Intent intent = new Intent();
- intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
- intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, account.getDescription());
- Parcelable iconResource = Intent.ShortcutIconResource.fromContext(this, R.drawable.icon);
- intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);
-
- // Now, return the result to the launcher
-
- setResult(RESULT_OK, intent);
- }
-
-
-}
-
-
diff --git a/src/com/android/email/activity/Accounts.java b/src/com/android/email/activity/Accounts.java
deleted file mode 100644
index c2c6521de..000000000
--- a/src/com/android/email/activity/Accounts.java
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.ListActivity;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.ContextMenu;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.View.OnClickListener;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-import android.widget.TextView;
-import android.widget.AdapterView.AdapterContextMenuInfo;
-import android.widget.AdapterView.OnItemClickListener;
-
-import com.android.email.Account;
-import com.android.email.Email;
-import com.android.email.MessagingController;
-import com.android.email.Preferences;
-import com.android.email.R;
-import com.android.email.activity.setup.AccountSettings;
-import com.android.email.activity.setup.AccountSetupBasics;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Store;
-import com.android.email.mail.store.LocalStore;
-import com.android.email.mail.store.LocalStore.LocalFolder;
-
-public class Accounts extends ListActivity implements OnItemClickListener, OnClickListener {
- private static final int DIALOG_REMOVE_ACCOUNT = 1;
- /**
- * Key codes used to open a debug settings screen.
- */
- private static int[] secretKeyCodes = {
- KeyEvent.KEYCODE_D, KeyEvent.KEYCODE_E, KeyEvent.KEYCODE_B, KeyEvent.KEYCODE_U,
- KeyEvent.KEYCODE_G
- };
-
- private int mSecretKeyCodeIndex = 0;
- private Account mSelectedContextAccount;
-
- /**
- * Start the Accounts list activity. Uses the CLEAR_TOP flag which means that other stacked
- * activities may be killed in order to get back to Accounts.
- */
- public static void actionShowAccounts(Context context) {
- Intent i = new Intent(context, Accounts.class);
- i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- context.startActivity(i);
- }
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- setContentView(R.layout.accounts);
- ListView listView = getListView();
- listView.setOnItemClickListener(this);
- listView.setItemsCanFocus(false);
- listView.setEmptyView(findViewById(R.id.empty));
- findViewById(R.id.add_new_account).setOnClickListener(this);
- registerForContextMenu(listView);
-
- if (icicle != null && icicle.containsKey("selectedContextAccount")) {
- mSelectedContextAccount = (Account) icicle.getSerializable("selectedContextAccount");
- }
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- if (mSelectedContextAccount != null) {
- outState.putSerializable("selectedContextAccount", mSelectedContextAccount);
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- NotificationManager notifMgr = (NotificationManager)
- getSystemService(Context.NOTIFICATION_SERVICE);
- notifMgr.cancel(1);
-
- refresh();
- }
-
- private void refresh() {
- Account[] accounts = Preferences.getPreferences(this).getAccounts();
- getListView().setAdapter(new AccountsAdapter(accounts));
- }
-
- private void onAddNewAccount() {
- AccountSetupBasics.actionNewAccount(this);
- }
-
- private void onEditAccount(Account account) {
- AccountSettings.actionSettings(this, account);
- }
-
- private void onRefresh() {
- MessagingController.getInstance(getApplication()).checkMail(this, null, null);
- }
-
- private void onCompose() {
- Account defaultAccount =
- Preferences.getPreferences(this).getDefaultAccount();
- if (defaultAccount != null) {
- MessageCompose.actionCompose(this, defaultAccount);
- }
- else {
- onAddNewAccount();
- }
- }
-
- private void onOpenAccount(Account account) {
- FolderMessageList.actionHandleAccount(this, account);
- }
-
- public void onClick(View view) {
- if (view.getId() == R.id.add_new_account) {
- onAddNewAccount();
- }
- }
-
- private void onDeleteAccount(Account account) {
- mSelectedContextAccount = account;
- showDialog(DIALOG_REMOVE_ACCOUNT);
- }
-
- @Override
- public Dialog onCreateDialog(int id) {
- switch (id) {
- case DIALOG_REMOVE_ACCOUNT:
- return createRemoveAccountDialog();
- }
- return super.onCreateDialog(id);
- }
-
- private Dialog createRemoveAccountDialog() {
- return new AlertDialog.Builder(this)
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setTitle(R.string.account_delete_dlg_title)
- .setMessage(getString(R.string.account_delete_dlg_instructions_fmt,
- mSelectedContextAccount.getDescription()))
- .setPositiveButton(R.string.okay_action, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- dismissDialog(DIALOG_REMOVE_ACCOUNT);
- try {
- ((LocalStore)Store.getInstance(
- mSelectedContextAccount.getLocalStoreUri(),
- getApplication())).delete();
- } catch (Exception e) {
- // Ignore
- }
- mSelectedContextAccount.delete(Preferences.getPreferences(Accounts.this));
- Email.setServicesEnabled(Accounts.this);
- refresh();
- }
- })
- .setNegativeButton(R.string.cancel_action, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- dismissDialog(DIALOG_REMOVE_ACCOUNT);
- }
- })
- .create();
- }
-
- public boolean onContextItemSelected(MenuItem item) {
- AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo)item.getMenuInfo();
- Account account = (Account)getListView().getItemAtPosition(menuInfo.position);
- switch (item.getItemId()) {
- case R.id.delete_account:
- onDeleteAccount(account);
- break;
- case R.id.edit_account:
- onEditAccount(account);
- break;
- case R.id.open:
- onOpenAccount(account);
- break;
- }
- return true;
- }
-
- public void onItemClick(AdapterView parent, View view, int position, long id) {
- Account account = (Account)parent.getItemAtPosition(position);
- onOpenAccount(account);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.add_new_account:
- onAddNewAccount();
- break;
- case R.id.check_mail:
- onRefresh();
- break;
- case R.id.compose:
- onCompose();
- break;
- default:
- return super.onOptionsItemSelected(item);
- }
- return true;
- }
-
- public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
- return true;
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- getMenuInflater().inflate(R.menu.accounts_option, menu);
- return true;
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
- menu.setHeaderTitle(R.string.accounts_context_menu_title);
- getMenuInflater().inflate(R.menu.accounts_context, menu);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (event.getKeyCode() == secretKeyCodes[mSecretKeyCodeIndex]) {
- mSecretKeyCodeIndex++;
- if (mSecretKeyCodeIndex == secretKeyCodes.length) {
- mSecretKeyCodeIndex = 0;
- startActivity(new Intent(this, Debug.class));
- }
- } else {
- mSecretKeyCodeIndex = 0;
- }
- return super.onKeyDown(keyCode, event);
- }
-
- class AccountsAdapter extends ArrayAdapter<Account> {
- public AccountsAdapter(Account[] accounts) {
- super(Accounts.this, 0, accounts);
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Account account = getItem(position);
- View view;
- if (convertView != null) {
- view = convertView;
- }
- else {
- view = getLayoutInflater().inflate(R.layout.accounts_item, parent, false);
- }
- AccountViewHolder holder = (AccountViewHolder) view.getTag();
- if (holder == null) {
- holder = new AccountViewHolder();
- holder.description = (TextView) view.findViewById(R.id.description);
- holder.email = (TextView) view.findViewById(R.id.email);
- holder.newMessageCount = (TextView) view.findViewById(R.id.new_message_count);
- view.setTag(holder);
- }
- holder.description.setText(account.getDescription());
- holder.email.setText(account.getEmail());
- if (account.getEmail().equals(account.getDescription())) {
- holder.email.setVisibility(View.GONE);
- }
- int unreadMessageCount = 0;
- try {
- LocalStore localStore = (LocalStore) Store.getInstance(
- account.getLocalStoreUri(),
- getApplication());
- LocalFolder localFolder = (LocalFolder) localStore.getFolder(Email.INBOX);
- if (localFolder.exists()) {
- unreadMessageCount = localFolder.getUnreadMessageCount();
- }
- }
- catch (MessagingException me) {
- /*
- * This is not expected to fail under normal circumstances.
- */
- throw new RuntimeException("Unable to get unread count from local store.", me);
- }
- holder.newMessageCount.setText(Integer.toString(unreadMessageCount));
- holder.newMessageCount.setVisibility(unreadMessageCount > 0 ? View.VISIBLE : View.GONE);
- return view;
- }
-
- class AccountViewHolder {
- public TextView description;
- public TextView email;
- public TextView newMessageCount;
- }
- }
-}
-
-
diff --git a/src/com/android/email/activity/Debug.java b/src/com/android/email/activity/Debug.java
deleted file mode 100644
index df1326e91..000000000
--- a/src/com/android/email/activity/Debug.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
-import android.widget.TextView;
-import android.widget.CompoundButton.OnCheckedChangeListener;
-
-import com.android.email.Email;
-import com.android.email.Preferences;
-import com.android.email.R;
-
-public class Debug extends Activity implements OnCheckedChangeListener {
- private TextView mVersionView;
- private CheckBox mEnableDebugLoggingView;
- private CheckBox mEnableSensitiveLoggingView;
-
- private Preferences mPreferences;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.debug);
-
- mPreferences = Preferences.getPreferences(this);
-
- mVersionView = (TextView)findViewById(R.id.version);
- mEnableDebugLoggingView = (CheckBox)findViewById(R.id.debug_logging);
- mEnableSensitiveLoggingView = (CheckBox)findViewById(R.id.sensitive_logging);
-
- mEnableDebugLoggingView.setOnCheckedChangeListener(this);
- mEnableSensitiveLoggingView.setOnCheckedChangeListener(this);
-
- mVersionView.setText(String.format(getString(R.string.debug_version_fmt).toString(),
- getString(R.string.build_number)));
-
- mEnableDebugLoggingView.setChecked(Email.DEBUG);
- mEnableSensitiveLoggingView.setChecked(Email.DEBUG_SENSITIVE);
- }
-
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (buttonView.getId() == R.id.debug_logging) {
- Email.DEBUG = isChecked;
- mPreferences.setEnableDebugLogging(Email.DEBUG);
- } else if (buttonView.getId() == R.id.sensitive_logging) {
- Email.DEBUG_SENSITIVE = isChecked;
- mPreferences.setEnableSensitiveLogging(Email.DEBUG_SENSITIVE);
- }
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- int id = item.getItemId();
- if (id == R.id.dump_settings) {
- Preferences.getPreferences(this).dump();
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- getMenuInflater().inflate(R.menu.debug_option, menu);
- return true;
- }
-
-}
diff --git a/src/com/android/email/activity/FolderMessageList.java b/src/com/android/email/activity/FolderMessageList.java
deleted file mode 100644
index c40226aab..000000000
--- a/src/com/android/email/activity/FolderMessageList.java
+++ /dev/null
@@ -1,1350 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity;
-
-import com.android.email.Account;
-import com.android.email.Email;
-import com.android.email.MessagingController;
-import com.android.email.MessagingListener;
-import com.android.email.Preferences;
-import com.android.email.R;
-import com.android.email.Utility;
-import com.android.email.activity.setup.AccountSettings;
-import com.android.email.mail.Address;
-import com.android.email.mail.AuthenticationFailedException;
-import com.android.email.mail.CertificateValidationException;
-import com.android.email.mail.Flag;
-import com.android.email.mail.Folder;
-import com.android.email.mail.Message;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Message.RecipientType;
-import com.android.email.mail.store.LocalStore;
-import com.android.email.mail.store.LocalStore.LocalMessage;
-
-import android.app.ExpandableListActivity;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Process;
-import android.util.Config;
-import android.util.Log;
-import android.view.ContextMenu;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.widget.BaseExpandableListAdapter;
-import android.widget.ExpandableListView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-import android.widget.Toast;
-import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
-
-import java.text.DateFormat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-
-/**
- * FolderMessageList is the primary user interface for the program. This Activity shows
- * a two level list of the Account's folders and each folder's messages. From this
- * Activity the user can perform all standard message operations.
- *
- *
- * TODO some things that are slowing us down:
- * Need a way to remove state such as progress bar and per folder progress on
- * resume if the command has completed.
- *
- * TODO
- * Break out seperate functions for:
- * refresh local folders
- * refresh remote folders
- * refresh open folder local messages
- * refresh open folder remote messages
- *
- * And don't refresh remote folders ever unless the user runs a refresh. Maybe not even then.
- */
-public class FolderMessageList extends ExpandableListActivity {
- private static final String EXTRA_ACCOUNT = "account";
- private static final String EXTRA_CLEAR_NOTIFICATION = "clearNotification";
- private static final String EXTRA_INITIAL_FOLDER = "initialFolder";
-
- private static final String STATE_KEY_LIST =
- "com.android.email.activity.folderlist_expandableListState";
- private static final String STATE_KEY_EXPANDED_GROUP =
- "com.android.email.activity.folderlist_expandedGroup";
- private static final String STATE_KEY_EXPANDED_GROUP_SELECTION =
- "com.android.email.activity.folderlist_expandedGroupSelection";
-
- private static final int UPDATE_FOLDER_ON_EXPAND_INTERVAL_MS = (1000 * 60 * 3);
-
- private static final int[] colorChipResIds = new int[] {
- R.drawable.appointment_indicator_leftside_1,
- R.drawable.appointment_indicator_leftside_2,
- R.drawable.appointment_indicator_leftside_3,
- R.drawable.appointment_indicator_leftside_4,
- R.drawable.appointment_indicator_leftside_5,
- R.drawable.appointment_indicator_leftside_6,
- R.drawable.appointment_indicator_leftside_7,
- R.drawable.appointment_indicator_leftside_8,
- R.drawable.appointment_indicator_leftside_9,
- R.drawable.appointment_indicator_leftside_10,
- R.drawable.appointment_indicator_leftside_11,
- R.drawable.appointment_indicator_leftside_12,
- R.drawable.appointment_indicator_leftside_13,
- R.drawable.appointment_indicator_leftside_14,
- R.drawable.appointment_indicator_leftside_15,
- R.drawable.appointment_indicator_leftside_16,
- R.drawable.appointment_indicator_leftside_17,
- R.drawable.appointment_indicator_leftside_18,
- R.drawable.appointment_indicator_leftside_19,
- R.drawable.appointment_indicator_leftside_20,
- R.drawable.appointment_indicator_leftside_21,
- };
-
- private ExpandableListView mListView;
- private int colorChipResId;
-
- private FolderMessageListAdapter mAdapter;
- private LayoutInflater mInflater;
- private Account mAccount;
- /**
- * Stores the name of the folder that we want to open as soon as possible after load. It is
- * set to null once the folder has been opened once.
- */
- private String mInitialFolder;
-
- private java.text.DateFormat mDateFormat;
- private java.text.DateFormat mTimeFormat;
-
- private int mExpandedGroup = -1;
- private boolean mRestoringState;
-
- private boolean mRefreshRemote;
-
- private FolderMessageListHandler mHandler = new FolderMessageListHandler();
-
- class FolderMessageListHandler extends Handler {
- private static final int MSG_PROGRESS = 2;
- private static final int MSG_DATA_CHANGED = 3;
- private static final int MSG_EXPAND_GROUP = 5;
- private static final int MSG_FOLDER_LOADING = 7;
- private static final int MSG_REMOVE_MESSAGE = 11;
- private static final int MSG_SYNC_MESSAGES = 13;
- private static final int MSG_FOLDER_STATUS = 17;
-
- @Override
- public void handleMessage(android.os.Message msg) {
- switch (msg.what) {
- case MSG_PROGRESS:
- setProgressBarIndeterminateVisibility(msg.arg1 != 0);
- break;
- case MSG_DATA_CHANGED:
- mAdapter.notifyDataSetChanged();
- break;
- case MSG_EXPAND_GROUP:
- mListView.expandGroup(msg.arg1);
- break;
- /*
- * The following functions modify the state of the adapter's underlying list and
- * must be run here, in the main thread, so that notifyDataSetChanged is run
- * before any further requests are made to the adapter.
- */
- case MSG_FOLDER_LOADING: {
- FolderInfoHolder folder = mAdapter.getFolder((String) msg.obj);
- if (folder != null) {
- folder.loading = msg.arg1 != 0;
- mAdapter.notifyDataSetChanged();
- }
- break;
- }
- case MSG_REMOVE_MESSAGE: {
- FolderInfoHolder folder = (FolderInfoHolder) ((Object[]) msg.obj)[0];
- MessageInfoHolder message = (MessageInfoHolder) ((Object[]) msg.obj)[1];
- folder.messages.remove(message);
- mAdapter.notifyDataSetChanged();
- break;
- }
- case MSG_SYNC_MESSAGES: {
- FolderInfoHolder folder = (FolderInfoHolder) ((Object[]) msg.obj)[0];
- Message[] messages = (Message[]) ((Object[]) msg.obj)[1];
- folder.messages.clear();
- for (Message message : messages) {
- mAdapter.addOrUpdateMessage(folder, message, false, false);
- }
- Collections.sort(folder.messages);
- mAdapter.notifyDataSetChanged();
- break;
- }
- case MSG_FOLDER_STATUS: {
- String folderName = (String) ((Object[]) msg.obj)[0];
- String status = (String) ((Object[]) msg.obj)[1];
- FolderInfoHolder folder = mAdapter.getFolder(folderName);
- if (folder != null) {
- folder.status = status;
- mAdapter.notifyDataSetChanged();
- }
- break;
- }
- default:
- super.handleMessage(msg);
- }
- }
-
- public void synchronizeMessages(FolderInfoHolder folder, Message[] messages) {
- android.os.Message msg = new android.os.Message();
- msg.what = MSG_SYNC_MESSAGES;
- msg.obj = new Object[] { folder, messages };
- sendMessage(msg);
- }
-
- public void removeMessage(FolderInfoHolder folder, MessageInfoHolder message) {
- android.os.Message msg = new android.os.Message();
- msg.what = MSG_REMOVE_MESSAGE;
- msg.obj = new Object[] { folder, message };
- sendMessage(msg);
- }
-
- public void folderLoading(String folder, boolean loading) {
- android.os.Message msg = new android.os.Message();
- msg.what = MSG_FOLDER_LOADING;
- msg.arg1 = loading ? 1 : 0;
- msg.obj = folder;
- sendMessage(msg);
- }
-
- public void progress(boolean progress) {
- android.os.Message msg = new android.os.Message();
- msg.what = MSG_PROGRESS;
- msg.arg1 = progress ? 1 : 0;
- sendMessage(msg);
- }
-
- public void dataChanged() {
- sendEmptyMessage(MSG_DATA_CHANGED);
- }
-
- public void expandGroup(int groupPosition) {
- android.os.Message msg = new android.os.Message();
- msg.what = MSG_EXPAND_GROUP;
- msg.arg1 = groupPosition;
- sendMessage(msg);
- }
-
- public void folderStatus(String folder, String status) {
- android.os.Message msg = new android.os.Message();
- msg.what = MSG_FOLDER_STATUS;
- msg.obj = new String[] { folder, status };
- sendMessage(msg);
- }
- }
-
- /**
- * This class is responsible for reloading the list of local messages for a given folder,
- * notifying the adapter that the message have been loaded and queueing up a remote
- * update of the folder.
- */
- static class FolderUpdateWorker implements Runnable {
- String mFolder;
- boolean mSynchronizeRemote;
- MessagingListener mListener;
- Account mAccount;
- MessagingController mController;
-
- /**
- * Create a worker for the given folder and specifying whether the
- * worker should synchronize the remote folder or just the local one.
- * @param folder
- * @param synchronizeRemote
- */
- public FolderUpdateWorker(String folder, boolean synchronizeRemote,
- MessagingListener listener, Account account, MessagingController controller) {
- mFolder = folder;
- mSynchronizeRemote = synchronizeRemote;
- mListener = listener;
- mAccount = account;
- mController = controller;
- }
-
- public void run() {
- // Lower our priority
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- // Synchronously load the list of local messages
- mController.listLocalMessages(
- mAccount,
- mFolder,
- mListener);
- if (mSynchronizeRemote) {
- // Tell the MessagingController to run a remote update of this folder
- // at it's leisure
- mController.synchronizeMailbox(
- mAccount,
- mFolder,
- mListener);
- }
- }
- }
-
- public static void actionHandleAccount(Context context, Account account, String initialFolder) {
- Intent intent = new Intent(context, FolderMessageList.class);
- intent.putExtra(EXTRA_ACCOUNT, account);
- if (initialFolder != null) {
- intent.putExtra(EXTRA_INITIAL_FOLDER, initialFolder);
- }
- context.startActivity(intent);
- }
-
- public static void actionHandleAccount(Context context, Account account) {
- actionHandleAccount(context, account, null);
- }
-
- public static Intent actionHandleAccountIntent(Context context, Account account, String initialFolder) {
- Intent intent = new Intent(context, FolderMessageList.class);
- intent.putExtra(EXTRA_ACCOUNT, account);
- intent.putExtra(EXTRA_CLEAR_NOTIFICATION, true);
- if (initialFolder != null) {
- intent.putExtra(EXTRA_INITIAL_FOLDER, initialFolder);
- }
- return intent;
- }
-
- /**
- * This should be used for generating lightweight (Uri-only) intents. It probably makes sense
- * to move entirely to this, and stop passing entire account structs through Intents.
- *
- * @param context Calling context for building the intent
- * @param account The account of interest
- * @param initialFolder If non-null, can set the folder name to open (typically Email.INBOX)
- * @return an Intent which can be used to view that account
- */
- public static Intent actionHandleAccountUriIntent(Context context, Account account,
- String initialFolder) {
- Intent i = actionHandleAccountIntent(context, account, initialFolder);
- i.removeExtra(EXTRA_ACCOUNT);
- i.setData(account.getContentUri());
- return i;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
-
- mDateFormat = android.text.format.DateFormat.getDateFormat(this); // short format
- mTimeFormat = android.text.format.DateFormat.getTimeFormat(this); // 12/24 date format
-
- mListView = getExpandableListView();
- mListView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_INSET);
- mListView.setLongClickable(true);
- registerForContextMenu(mListView);
-
- /*
- * We manually save and restore the list's state because our adapter is slow.
- */
- mListView.setSaveEnabled(false);
-
- getExpandableListView().setGroupIndicator(
- getResources().getDrawable(R.drawable.expander_ic_folder));
-
- mInflater = getLayoutInflater();
-
- Intent intent = getIntent();
- mAccount = (Account)intent.getSerializableExtra(EXTRA_ACCOUNT);
- if (mAccount == null) {
- Uri uri = intent.getData();
- if (uri != null) {
- mAccount = Preferences.getPreferences(this).getAccountByContentUri(uri);
- }
- }
- // If no useable account was specified, just go to the accounts list screen instead
- if (mAccount == null) {
- Accounts.actionShowAccounts(this);
- finish();
- return;
- }
-
- // Take the initial folder into account only if we are *not* restoring the activity already
- if (savedInstanceState == null) {
- mInitialFolder = intent.getStringExtra(EXTRA_INITIAL_FOLDER);
- }
-
- /*
- * Since the color chip is always the same color for a given account we just cache the id
- * of the chip right here.
- */
- colorChipResId = colorChipResIds[mAccount.getAccountNumber() % colorChipResIds.length];
-
- mAdapter = new FolderMessageListAdapter();
-
- final Object previousData = getLastNonConfigurationInstance();
- if (previousData != null) {
- //noinspection unchecked
- mAdapter.mFolders = (ArrayList<FolderInfoHolder>) previousData;
- }
-
- setListAdapter(mAdapter);
-
- if (savedInstanceState != null) {
- mRestoringState = true;
- onRestoreListState(savedInstanceState);
- mRestoringState = false;
- }
-
- setTitle(mAccount.getDescription());
- }
-
- private void onRestoreListState(Bundle savedInstanceState) {
- final int expandedGroup = savedInstanceState.getInt(STATE_KEY_EXPANDED_GROUP, -1);
- if (expandedGroup >= 0 && mAdapter.getGroupCount() > expandedGroup) {
- mListView.expandGroup(expandedGroup);
- long selectedChild = savedInstanceState.getLong(STATE_KEY_EXPANDED_GROUP_SELECTION, -1);
- if (selectedChild != ExpandableListView.PACKED_POSITION_VALUE_NULL) {
- mListView.setSelection(mListView.getFlatListPosition(selectedChild));
- }
- }
- mListView.onRestoreInstanceState(savedInstanceState.getParcelable(STATE_KEY_LIST));
- }
-
- @Override
- public Object onRetainNonConfigurationInstance() {
- return mAdapter.mFolders;
- }
-
- @Override
- public void onPause() {
- super.onPause();
- MessagingController.getInstance(getApplication()).removeListener(mAdapter.mListener);
- }
-
- /**
- * On resume we refresh the folder list (in the background) and we refresh the messages
- * for any folder that is currently open. This guarantees that things like unread message
- * count and read status are updated.
- */
- @Override
- public void onResume() {
- super.onResume();
-
- NotificationManager notifMgr = (NotificationManager)
- getSystemService(Context.NOTIFICATION_SERVICE);
- notifMgr.cancel(1);
-
- MessagingController.getInstance(getApplication()).addListener(mAdapter.mListener);
- mAccount.refresh(Preferences.getPreferences(this));
- onRefresh(false);
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putParcelable(STATE_KEY_LIST, mListView.onSaveInstanceState());
- outState.putInt(STATE_KEY_EXPANDED_GROUP, mExpandedGroup);
- outState.putLong(STATE_KEY_EXPANDED_GROUP_SELECTION, mListView.getSelectedPosition());
- }
-
- @Override
- public void onGroupCollapse(int groupPosition) {
- super.onGroupCollapse(groupPosition);
- mExpandedGroup = -1;
- }
-
- @Override
- public void onGroupExpand(int groupPosition) {
- super.onGroupExpand(groupPosition);
- if (mExpandedGroup != -1) {
- mListView.collapseGroup(mExpandedGroup);
- }
- mExpandedGroup = groupPosition;
-
- if (!mRestoringState) {
- /*
- * Scroll the selected item to the top of the screen.
- */
- int position = mListView.getFlatListPosition(
- ExpandableListView.getPackedPositionForGroup(groupPosition));
- mListView.setSelectionFromTop(position, 0);
- }
-
- final FolderInfoHolder folder = (FolderInfoHolder) mAdapter.getGroup(groupPosition);
- /*
- * We'll only do a hard refresh of a particular folder every 3 minutes or if the user
- * specifically asks for a refresh.
- */
- if (System.currentTimeMillis() - folder.lastChecked
- > UPDATE_FOLDER_ON_EXPAND_INTERVAL_MS) {
- folder.lastChecked = System.currentTimeMillis();
- // TODO: If the previous thread is already running, we should cancel it
- new Thread(new FolderUpdateWorker(folder.name, true, null, mAccount,
- MessagingController.getInstance(getApplication())))
- .start();
- }
- }
-
- @Override
- public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
- int childPosition, long id) {
- FolderInfoHolder folder = (FolderInfoHolder) mAdapter.getGroup(groupPosition);
- if (folder.outbox) {
- return false;
- }
- if (childPosition == folder.messages.size() && !folder.loading) {
- if (folder.status == null) {
- MessagingController.getInstance(getApplication()).loadMoreMessages(
- mAccount,
- folder.name,
- mAdapter.mListener);
- return false;
- }
- else {
- MessagingController.getInstance(getApplication()).synchronizeMailbox(
- mAccount,
- folder.name,
- mAdapter.mListener);
- return false;
- }
- }
- else if (childPosition >= folder.messages.size()) {
- return false;
- }
- MessageInfoHolder message = (MessageInfoHolder) mAdapter.getChild(groupPosition, childPosition);
-
- onOpenMessage(folder, message);
-
- return true;
- }
-
- private void onRefresh(final boolean forceRemote) {
- if (forceRemote) {
- mRefreshRemote = true;
- }
- new Thread() {
- public void run() {
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- MessagingController.getInstance(getApplication()).listFolders(
- mAccount,
- forceRemote,
- mAdapter.mListener);
- if (forceRemote) {
- MessagingController.getInstance(getApplication()).sendPendingMessages(
- mAccount,
- null);
- }
- }
- }.start();
- }
-
- private void onOpenMessage(FolderInfoHolder folder, MessageInfoHolder message) {
- /*
- * We set read=true here for UI performance reasons. The actual value will get picked up
- * on the refresh when the Activity is resumed but that may take a second or so and we
- * don't want this to show and then go away.
- * I've gone back and forth on this, and this gives a better UI experience, so I am
- * putting it back in.
- */
- if (!message.read) {
- message.read = true;
- mHandler.dataChanged();
- }
-
- if (folder.name.equals(mAccount.getDraftsFolderName())) {
- MessageCompose.actionEditDraft(this, mAccount, message.message);
- }
- else {
- ArrayList<String> folderUids = new ArrayList<String>();
- for (MessageInfoHolder holder : folder.messages) {
- folderUids.add(holder.uid);
- }
- MessageView.actionView(this, mAccount, folder.name, message.uid, folderUids);
- }
- }
-
- private void onEditAccount() {
- AccountSettings.actionSettings(this, mAccount);
- }
-
- private void onAccounts() {
- Accounts.actionShowAccounts(this);
- finish();
- }
-
- private void onCompose() {
- MessageCompose.actionCompose(this, mAccount);
- }
-
- private void onDelete(MessageInfoHolder holder) {
- MessagingController.getInstance(getApplication()).deleteMessage(
- mAccount,
- holder.message.getFolder().getName(),
- holder.message,
- null);
- mAdapter.removeMessage(holder.message.getFolder().getName(), holder.uid);
- Toast.makeText(this, R.string.message_deleted_toast, Toast.LENGTH_SHORT).show();
- }
-
- private void onReply(MessageInfoHolder holder) {
- MessageCompose.actionReply(this, mAccount, holder.message, false);
- }
-
- private void onReplyAll(MessageInfoHolder holder) {
- MessageCompose.actionReply(this, mAccount, holder.message, true);
- }
-
- private void onForward(MessageInfoHolder holder) {
- MessageCompose.actionForward(this, mAccount, holder.message);
- }
-
- private void onToggleRead(MessageInfoHolder holder) {
- MessagingController.getInstance(getApplication()).markMessageRead(
- mAccount,
- holder.message.getFolder().getName(),
- holder.uid,
- !holder.read);
- holder.read = !holder.read;
- onRefresh(false);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.refresh:
- onRefresh(true);
- return true;
- case R.id.accounts:
- onAccounts();
- return true;
- case R.id.compose:
- onCompose();
- return true;
- case R.id.account_settings:
- onEditAccount();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- getMenuInflater().inflate(R.menu.folder_message_list_option, menu);
- return true;
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- ExpandableListContextMenuInfo info =
- (ExpandableListContextMenuInfo) item.getMenuInfo();
- int groupPosition =
- ExpandableListView.getPackedPositionGroup(info.packedPosition);
- int childPosition =
- ExpandableListView.getPackedPositionChild(info.packedPosition);
- FolderInfoHolder folder = (FolderInfoHolder) mAdapter.getGroup(groupPosition);
- if (childPosition < mAdapter.getChildrenCount(groupPosition)) {
- MessageInfoHolder holder =
- (MessageInfoHolder) mAdapter.getChild(groupPosition, childPosition);
- switch (item.getItemId()) {
- case R.id.open:
- onOpenMessage(folder, holder);
- break;
- case R.id.delete:
- onDelete(holder);
- break;
- case R.id.reply:
- onReply(holder);
- break;
- case R.id.reply_all:
- onReplyAll(holder);
- break;
- case R.id.forward:
- onForward(holder);
- break;
- case R.id.mark_as_read:
- onToggleRead(holder);
- break;
- }
- }
- return super.onContextItemSelected(item);
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
- ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuInfo;
- if (ExpandableListView.getPackedPositionType(info.packedPosition) ==
- ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
- long packedPosition = info.packedPosition;
- int groupPosition = ExpandableListView.getPackedPositionGroup(packedPosition);
- int childPosition = ExpandableListView.getPackedPositionChild(packedPosition);
- FolderInfoHolder folder = (FolderInfoHolder) mAdapter.getGroup(groupPosition);
- if (folder.outbox) {
- return;
- }
- if (childPosition < folder.messages.size()) {
- getMenuInflater().inflate(R.menu.folder_message_list_context, menu);
- MessageInfoHolder message =
- (MessageInfoHolder) mAdapter.getChild(groupPosition, childPosition);
- if (message.read) {
- menu.findItem(R.id.mark_as_read).setTitle(R.string.mark_as_unread_action);
- }
- }
- }
- }
-
- class FolderMessageListAdapter extends BaseExpandableListAdapter {
- private ArrayList<FolderInfoHolder> mFolders = new ArrayList<FolderInfoHolder>();
-
- private MessagingListener mListener = new MessagingListener() {
- @Override
- public void listFoldersStarted(Account account) {
- if (!account.equals(mAccount)) {
- return;
- }
- mHandler.progress(true);
- }
-
- @Override
- public void listFoldersFailed(Account account, String message) {
- if (!account.equals(mAccount)) {
- return;
- }
- mHandler.progress(false);
- if (Config.LOGV) {
- Log.v(Email.LOG_TAG, "listFoldersFailed " + message);
- }
- }
-
- @Override
- public void listFoldersFinished(Account account) {
- if (!account.equals(mAccount)) {
- return;
- }
- mHandler.progress(false);
- if (mInitialFolder != null) {
- int groupPosition = getFolderPosition(mInitialFolder);
- mInitialFolder = null;
- if (groupPosition != -1) {
- mHandler.expandGroup(groupPosition);
- }
- }
- }
-
- @Override
- public void listFolders(Account account, Folder[] folders) {
- if (!account.equals(mAccount)) {
- return;
- }
- for (Folder folder : folders) {
- FolderInfoHolder holder = getFolder(folder.getName());
- if (holder == null) {
- holder = new FolderInfoHolder();
- mFolders.add(holder);
- }
- holder.name = folder.getName();
- if (holder.name.equalsIgnoreCase(Email.INBOX)) {
- holder.displayName = getString(R.string.special_mailbox_name_inbox);
- }
- else {
- holder.displayName = folder.getName();
- }
- if (holder.name.equals(mAccount.getOutboxFolderName())) {
- holder.outbox = true;
- }
- if (holder.messages == null) {
- holder.messages = new ArrayList<MessageInfoHolder>();
- }
- try {
- folder.open(Folder.OpenMode.READ_WRITE);
- holder.unreadMessageCount = folder.getUnreadMessageCount();
- folder.close(false);
- }
- catch (MessagingException me) {
- Log.e(Email.LOG_TAG, "Folder.getUnreadMessageCount() failed", me);
- }
- }
-
- Collections.sort(mFolders);
- mHandler.dataChanged();
-
-
- /*
- * We will do this eventually. This restores the state of the list in the
- * case of a killed Activity but we have some message sync issues to take care of.
- */
-// if (mRestoredState != null) {
-// if (Config.LOGV) {
-// Log.v(Email.LOG_TAG, "Attempting to restore list state");
-// }
-// Parcelable listViewState =
-// mListView.onRestoreInstanceState(mListViewState);
-// mListViewState = null;
-// }
-
- /*
- * Now we need to refresh any folders that are currently expanded. We do this
- * in case the status or amount of messages has changed.
- */
- for (int i = 0, count = getGroupCount(); i < count; i++) {
- if (mListView.isGroupExpanded(i)) {
- final FolderInfoHolder folder = (FolderInfoHolder) mAdapter.getGroup(i);
- new Thread(new FolderUpdateWorker(folder.name, mRefreshRemote, null,
- mAccount, MessagingController.getInstance(getApplication())))
- .start();
- }
- }
- mRefreshRemote = false;
- }
-
- @Override
- public void listLocalMessagesStarted(Account account, String folder) {
- if (!account.equals(mAccount)) {
- return;
- }
- mHandler.progress(true);
- mHandler.folderLoading(folder, true);
- }
-
- @Override
- public void listLocalMessagesFailed(Account account, String folder, String message) {
- if (!account.equals(mAccount)) {
- return;
- }
- mHandler.progress(false);
- mHandler.folderLoading(folder, false);
- }
-
- @Override
- public void listLocalMessagesFinished(Account account, String folder) {
- if (!account.equals(mAccount)) {
- return;
- }
- mHandler.progress(false);
- mHandler.folderLoading(folder, false);
- }
-
- @Override
- public void listLocalMessages(Account account, String folder, Message[] messages) {
- if (!account.equals(mAccount)) {
- return;
- }
- synchronizeMessages(folder, messages);
- }
-
- @Override
- public void synchronizeMailboxStarted(
- Account account,
- String folder) {
- if (!account.equals(mAccount)) {
- return;
- }
- mHandler.progress(true);
- mHandler.folderLoading(folder, true);
- mHandler.folderStatus(folder, null);
- }
-
- @Override
- public void synchronizeMailboxFinished(
- Account account,
- String folder,
- int totalMessagesInMailbox,
- int numNewMessages) {
- if (!account.equals(mAccount)) {
- return;
- }
- mHandler.progress(false);
- mHandler.folderLoading(folder, false);
- mHandler.folderStatus(folder, null);
- onRefresh(false);
- }
-
- @Override
- public void synchronizeMailboxFailed(Account account, String folder, Exception e) {
- if (!account.equals(mAccount)) {
- return;
- }
- mHandler.progress(false);
- mHandler.folderLoading(folder, false);
- // Use exception details to select a decent string
- // TODO combine with very similar code in AccountSettingsCheckSetup
- int id = R.string.status_network_error;
- if (e instanceof AuthenticationFailedException) {
- id = R.string.account_setup_failed_dlg_auth_message;
- } else if (e instanceof CertificateValidationException) {
- id = R.string.account_setup_failed_dlg_certificate_message;
- } else if (e instanceof MessagingException) {
- MessagingException me = (MessagingException) e;
- switch (me.getExceptionType()) {
- case MessagingException.IOERROR:
- id = R.string.account_setup_failed_ioerror;
- break;
- case MessagingException.TLS_REQUIRED:
- id = R.string.account_setup_failed_tls_required;
- break;
- case MessagingException.AUTH_REQUIRED:
- id = R.string.account_setup_failed_auth_required;
- break;
- case MessagingException.GENERAL_SECURITY:
- id = R.string.account_setup_failed_security;
- break;
- }
- }
- mHandler.folderStatus(folder, getString(id));
- FolderInfoHolder holder = getFolder(folder);
- if (holder != null) {
- /*
- * Reset the last checked time to 0 so that the next expand will attempt to
- * refresh this folder.
- */
- holder.lastChecked = 0;
- }
- }
-
- @Override
- public void synchronizeMailboxNewMessage(
- Account account,
- String folder,
- Message message) {
- if (!account.equals(mAccount)) {
- return;
- }
- addOrUpdateMessage(folder, message);
- }
-
- @Override
- public void synchronizeMailboxRemovedMessage(
- Account account,
- String folder,
- Message message) {
- if (!account.equals(mAccount)) {
- return;
- }
- removeMessage(folder, message.getUid());
- }
-
- @Override
- public void emptyTrashCompleted(Account account) {
- if (!account.equals(mAccount)) {
- return;
- }
- onRefresh(false);
- }
-
- @Override
- public void sendPendingMessagesCompleted(Account account) {
- if (!account.equals(mAccount)) {
- return;
- }
- onRefresh(false);
- }
-
- @Override
- public void messageUidChanged(
- Account account,
- String folder,
- String oldUid,
- String newUid) {
- if (mAccount.equals(account)) {
- FolderInfoHolder holder = getFolder(folder);
- if (folder != null) {
- for (MessageInfoHolder message : holder.messages) {
- if (message.uid.equals(oldUid)) {
- message.uid = newUid;
- message.message.setUid(newUid);
- }
- }
- }
- }
- }
- };
-
- private Drawable mAttachmentIcon;
-
- FolderMessageListAdapter() {
- mAttachmentIcon = getResources().getDrawable(R.drawable.ic_mms_attachment_small);
- }
-
- public void removeMessage(String folder, String messageUid) {
- FolderInfoHolder f = getFolder(folder);
- if (f == null) {
- return;
- }
- MessageInfoHolder m = getMessage(f, messageUid);
- if (m == null) {
- return;
- }
- mHandler.removeMessage(f, m);
- }
-
- public void synchronizeMessages(String folder, Message[] messages) {
- FolderInfoHolder f = getFolder(folder);
- if (f == null) {
- return;
- }
- mHandler.synchronizeMessages(f, messages);
- }
-
- public void addOrUpdateMessage(String folder, Message message) {
- addOrUpdateMessage(folder, message, true, true);
- }
-
- private void addOrUpdateMessage(FolderInfoHolder folder, Message message,
- boolean sort, boolean notify) {
- MessageInfoHolder m = getMessage(folder, message.getUid());
- if (m == null) {
- m = new MessageInfoHolder(message, folder, mDateFormat, mTimeFormat);
- folder.messages.add(m);
- }
- else {
- m.populate(message, folder);
- }
- if (sort) {
- Collections.sort(folder.messages);
- }
- if (notify) {
- mHandler.dataChanged();
- }
- }
-
- private void addOrUpdateMessage(String folder, Message message,
- boolean sort, boolean notify) {
- FolderInfoHolder f = getFolder(folder);
- if (f == null) {
- return;
- }
- addOrUpdateMessage(f, message, sort, notify);
- }
-
- public MessageInfoHolder getMessage(FolderInfoHolder folder, String messageUid) {
- for (MessageInfoHolder message : folder.messages) {
- if (message.uid.equals(messageUid)) {
- return message;
- }
- }
- return null;
- }
-
- public int getGroupCount() {
- return mFolders.size();
- }
-
- public long getGroupId(int groupPosition) {
- return groupPosition;
- }
-
- public Object getGroup(int groupPosition) {
- return mFolders.get(groupPosition);
- }
-
- public FolderInfoHolder getFolder(String folder) {
- FolderInfoHolder folderHolder = null;
- for (int i = 0, count = getGroupCount(); i < count; i++) {
- FolderInfoHolder holder = (FolderInfoHolder) getGroup(i);
- if (holder.name.equals(folder)) {
- folderHolder = holder;
- }
- }
- return folderHolder;
- }
-
- /**
- * Gets the group position of the given folder or returns -1 if the folder is not
- * found.
- * @param folder
- * @return
- */
- public int getFolderPosition(String folder) {
- for (int i = 0, count = getGroupCount(); i < count; i++) {
- FolderInfoHolder holder = (FolderInfoHolder) getGroup(i);
- if (holder.name.equals(folder)) {
- return i;
- }
- }
- return -1;
- }
-
- public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
- ViewGroup parent) {
- FolderInfoHolder folder = (FolderInfoHolder) getGroup(groupPosition);
- View view;
- if (convertView != null) {
- view = convertView;
- } else {
- view = mInflater.inflate(R.layout.folder_message_list_group, parent, false);
- }
- FolderViewHolder holder = (FolderViewHolder) view.getTag();
- if (holder == null) {
- holder = new FolderViewHolder();
- holder.folderName = (TextView) view.findViewById(R.id.folder_name);
- holder.newMessageCount = (TextView) view.findViewById(R.id.new_message_count);
- holder.folderStatus = (TextView) view.findViewById(R.id.folder_status);
- view.setTag(holder);
- }
- holder.folderName.setText(folder.displayName);
-
- if (folder.status == null) {
- holder.folderStatus.setVisibility(View.GONE);
- }
- else {
- holder.folderStatus.setText(folder.status);
- holder.folderStatus.setVisibility(View.VISIBLE);
- }
-
- if (folder.unreadMessageCount != 0) {
- holder.newMessageCount.setText(Integer.toString(folder.unreadMessageCount));
- holder.newMessageCount.setVisibility(View.VISIBLE);
- }
- else {
- holder.newMessageCount.setVisibility(View.GONE);
- }
- return view;
- }
-
- public int getChildrenCount(int groupPosition) {
- FolderInfoHolder folder = (FolderInfoHolder) getGroup(groupPosition);
- return folder.messages.size() + 1;
- }
-
- public long getChildId(int groupPosition, int childPosition) {
- FolderInfoHolder folder = (FolderInfoHolder) getGroup(groupPosition);
- if (childPosition < folder.messages.size()) {
- MessageInfoHolder holder = folder.messages.get(childPosition);
- return ((LocalStore.LocalMessage) holder.message).getId();
- } else {
- return -1;
- }
- }
-
- public Object getChild(int groupPosition, int childPosition) {
- FolderInfoHolder folder = (FolderInfoHolder) getGroup(groupPosition);
- return folder.messages.get(childPosition);
- }
-
- public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
- View convertView, ViewGroup parent) {
- FolderInfoHolder folder = (FolderInfoHolder) getGroup(groupPosition);
- if (isLastChild) {
- View view;
- if ((convertView != null)
- && (convertView.getId()
- == R.layout.folder_message_list_child_footer)) {
- view = convertView;
- }
- else {
- view = mInflater.inflate(R.layout.folder_message_list_child_footer,
- parent, false);
- view.setId(R.layout.folder_message_list_child_footer);
- }
- FooterViewHolder holder = (FooterViewHolder) view.getTag();
- if (holder == null) {
- holder = new FooterViewHolder();
- holder.progress = (ProgressBar) view.findViewById(R.id.progress);
- holder.main = (TextView) view.findViewById(R.id.main_text);
- view.setTag(holder);
- }
- if (folder.loading) {
- holder.main.setText(getString(R.string.status_loading_more));
- holder.progress.setVisibility(View.VISIBLE);
- }
- else {
- if (folder.status == null) {
- holder.main.setText(getString(R.string.message_list_load_more_messages_action));
- }
- else {
- holder.main.setText(getString(R.string.status_loading_more_failed));
- }
- holder.progress.setVisibility(View.GONE);
- }
- return view;
- }
- else {
- MessageInfoHolder message =
- (MessageInfoHolder) getChild(groupPosition, childPosition);
- View view;
- if ((convertView != null)
- && (convertView.getId() != R.layout.folder_message_list_child_footer)) {
- view = convertView;
- } else {
- view = mInflater.inflate(R.layout.folder_message_list_child, parent, false);
- }
- MessageViewHolder holder = (MessageViewHolder) view.getTag();
- if (holder == null) {
- holder = new MessageViewHolder();
- holder.subject = (TextView) view.findViewById(R.id.subject);
- holder.from = (TextView) view.findViewById(R.id.from);
- holder.date = (TextView) view.findViewById(R.id.date);
- holder.chip = view.findViewById(R.id.chip);
- /*
- * TODO
- * The line below and the commented lines a bit further down are work
- * in progress for outbox status. They should not be removed.
- */
-// holder.status = (TextView) view.findViewById(R.id.status);
-
- /*
- * This will need to move to below if we ever convert this whole thing
- * to a combined inbox.
- */
- holder.chip.setBackgroundResource(colorChipResId);
-
- view.setTag(holder);
- }
- holder.chip.getBackground().setAlpha(message.read ? 0 : 255);
- holder.subject.setText(message.subject);
- holder.subject.setTypeface(null, message.read ? Typeface.NORMAL : Typeface.BOLD);
- holder.from.setText(message.sender);
- holder.from.setTypeface(null, message.read ? Typeface.NORMAL : Typeface.BOLD);
- holder.date.setText(message.date);
- holder.from.setCompoundDrawablesWithIntrinsicBounds(null, null,
- message.hasAttachments ? mAttachmentIcon : null, null);
-// if (folder.outbox) {
-// holder.status.setText("Sending");
-// }
-// else {
-// holder.status.setText("");
-// }
- return view;
- }
- }
-
- public boolean hasStableIds() {
- return true;
- }
-
- public boolean isChildSelectable(int groupPosition, int childPosition) {
- return childPosition < getChildrenCount(groupPosition);
- }
-
- }
-
- /**
- * Holder for a single folder's information.
- */
- static class FolderInfoHolder implements Comparable<FolderInfoHolder> {
- public String name;
- public String displayName;
- public ArrayList<MessageInfoHolder> messages;
- public long lastChecked;
- public int unreadMessageCount;
- public boolean loading;
- public String status;
- public boolean lastCheckFailed;
-
- /**
- * Outbox is handled differently from any other folder.
- */
- public boolean outbox;
-
- public int compareTo(FolderInfoHolder o) {
- String s1 = this.name;
- String s2 = o.name;
- if (Email.INBOX.equalsIgnoreCase(s1)) {
- return -1;
- } else if (Email.INBOX.equalsIgnoreCase(s2)) {
- return 1;
- } else
- return s1.toUpperCase().compareTo(s2.toUpperCase());
- }
- }
-
- /**
- * Holder for a single message's information.
- */
- static class MessageInfoHolder implements Comparable<MessageInfoHolder> {
- public String subject;
- public String date;
- public Date compareDate;
- public String sender;
- public boolean hasAttachments;
- public String uid;
- public boolean read;
- public Message message;
-
- private java.text.DateFormat mDateFormat;
- private java.text.DateFormat mTimeFormat;
-
- public MessageInfoHolder(Message m, FolderInfoHolder folder, DateFormat formatForDate,
- DateFormat formatForTime) {
- mDateFormat = formatForDate;
- mTimeFormat = formatForTime;
- populate(m, folder);
- }
-
- public void populate(Message m, FolderInfoHolder folder) {
- try {
- LocalMessage message = (LocalMessage) m;
- Date date = message.getSentDate();
- this.compareDate = date;
- if (Utility.isDateToday(date)) {
- this.date = mTimeFormat.format(date);
- }
- else {
- this.date = mDateFormat.format(date);
- }
- this.hasAttachments = message.getAttachmentCount() > 0;
- this.read = message.isSet(Flag.SEEN);
- if (folder.outbox) {
- this.sender = Address.toFriendly(
- message.getRecipients(RecipientType.TO));
- }
- else {
- this.sender = Address.toFriendly(message.getFrom());
- }
- this.subject = message.getSubject();
- this.uid = message.getUid();
- this.message = m;
- }
- catch (MessagingException me) {
- if (Config.LOGV) {
- Log.v(Email.LOG_TAG, "Unable to load message info", me);
- }
- }
- }
-
- public int compareTo(MessageInfoHolder o) {
- return this.compareDate.compareTo(o.compareDate) * -1;
- }
- }
-
- static class FolderViewHolder {
- public TextView folderName;
- public TextView folderStatus;
- public TextView newMessageCount;
- }
-
- static class MessageViewHolder {
- public TextView subject;
- public TextView preview;
- public TextView from;
- public TextView date;
- public View chip;
- }
-
- static class FooterViewHolder {
- public ProgressBar progress;
- public TextView main;
- }
-
-
-}
diff --git a/src/com/android/email/activity/MessageCompose.java b/src/com/android/email/activity/MessageCompose.java
deleted file mode 100644
index 64878e274..000000000
--- a/src/com/android/email/activity/MessageCompose.java
+++ /dev/null
@@ -1,1282 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity;
-
-import com.android.email.Account;
-import com.android.email.Email;
-import com.android.email.EmailAddressAdapter;
-import com.android.email.EmailAddressValidator;
-import com.android.email.MessagingController;
-import com.android.email.MessagingListener;
-import com.android.email.Preferences;
-import com.android.email.R;
-import com.android.email.Utility;
-import com.android.email.mail.Address;
-import com.android.email.mail.Body;
-import com.android.email.mail.Message;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Multipart;
-import com.android.email.mail.Part;
-import com.android.email.mail.Message.RecipientType;
-import com.android.email.mail.internet.MimeBodyPart;
-import com.android.email.mail.internet.MimeHeader;
-import com.android.email.mail.internet.MimeMessage;
-import com.android.email.mail.internet.MimeMultipart;
-import com.android.email.mail.internet.MimeUtility;
-import com.android.email.mail.internet.TextBody;
-import com.android.email.mail.store.LocalStore;
-import com.android.email.mail.store.LocalStore.LocalAttachmentBody;
-
-import android.app.Activity;
-import android.content.ActivityNotFoundException;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Parcelable;
-import android.provider.OpenableColumns;
-import android.text.InputFilter;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-import android.text.TextWatcher;
-import android.text.util.Rfc822Tokenizer;
-import android.util.Config;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.Window;
-import android.view.View.OnClickListener;
-import android.view.View.OnFocusChangeListener;
-import android.webkit.WebView;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
-import android.widget.MultiAutoCompleteTextView;
-import android.widget.TextView;
-import android.widget.Toast;
-import android.widget.AutoCompleteTextView.Validator;
-
-import java.io.Serializable;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-public class MessageCompose extends Activity implements OnClickListener, OnFocusChangeListener {
- private static final String ACTION_REPLY = "com.android.email.intent.action.REPLY";
- private static final String ACTION_REPLY_ALL = "com.android.email.intent.action.REPLY_ALL";
- private static final String ACTION_FORWARD = "com.android.email.intent.action.FORWARD";
- private static final String ACTION_EDIT_DRAFT = "com.android.email.intent.action.EDIT_DRAFT";
-
- private static final String EXTRA_ACCOUNT = "account";
- private static final String EXTRA_FOLDER = "folder";
- private static final String EXTRA_MESSAGE = "message";
-
- private static final String STATE_KEY_ATTACHMENTS =
- "com.android.email.activity.MessageCompose.attachments";
- private static final String STATE_KEY_CC_SHOWN =
- "com.android.email.activity.MessageCompose.ccShown";
- private static final String STATE_KEY_BCC_SHOWN =
- "com.android.email.activity.MessageCompose.bccShown";
- private static final String STATE_KEY_QUOTED_TEXT_SHOWN =
- "com.android.email.activity.MessageCompose.quotedTextShown";
- private static final String STATE_KEY_SOURCE_MESSAGE_PROCED =
- "com.android.email.activity.MessageCompose.stateKeySourceMessageProced";
- private static final String STATE_KEY_DRAFT_UID =
- "com.android.email.activity.MessageCompose.draftUid";
-
- private static final int MSG_PROGRESS_ON = 1;
- private static final int MSG_PROGRESS_OFF = 2;
- private static final int MSG_UPDATE_TITLE = 3;
- private static final int MSG_SKIPPED_ATTACHMENTS = 4;
- private static final int MSG_SAVED_DRAFT = 5;
- private static final int MSG_DISCARDED_DRAFT = 6;
-
- private static final int ACTIVITY_REQUEST_PICK_ATTACHMENT = 1;
-
- private Account mAccount;
- private String mFolder;
- private String mSourceMessageUid;
- private Message mSourceMessage;
- /**
- * Indicates that the source message has been processed at least once and should not
- * be processed on any subsequent loads. This protects us from adding attachments that
- * have already been added from the restore of the view state.
- */
- private boolean mSourceMessageProcessed = false;
-
- private MultiAutoCompleteTextView mToView;
- private MultiAutoCompleteTextView mCcView;
- private MultiAutoCompleteTextView mBccView;
- private EditText mSubjectView;
- private EditText mMessageContentView;
- private Button mSendButton;
- private Button mDiscardButton;
- private Button mSaveButton;
- private LinearLayout mAttachments;
- private View mQuotedTextBar;
- private ImageButton mQuotedTextDelete;
- private WebView mQuotedText;
-
- private boolean mDraftNeedsSaving = false;
-
- /**
- * The draft uid of this message. This is used when saving drafts so that the same draft is
- * overwritten instead of being created anew. This property is null until the first save.
- */
- private String mDraftUid;
-
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(android.os.Message msg) {
- switch (msg.what) {
- case MSG_PROGRESS_ON:
- setProgressBarIndeterminateVisibility(true);
- break;
- case MSG_PROGRESS_OFF:
- setProgressBarIndeterminateVisibility(false);
- break;
- case MSG_UPDATE_TITLE:
- updateTitle();
- break;
- case MSG_SKIPPED_ATTACHMENTS:
- Toast.makeText(
- MessageCompose.this,
- getString(R.string.message_compose_attachments_skipped_toast),
- Toast.LENGTH_LONG).show();
- break;
- case MSG_SAVED_DRAFT:
- Toast.makeText(
- MessageCompose.this,
- getString(R.string.message_saved_toast),
- Toast.LENGTH_LONG).show();
- break;
- case MSG_DISCARDED_DRAFT:
- Toast.makeText(
- MessageCompose.this,
- getString(R.string.message_discarded_toast),
- Toast.LENGTH_LONG).show();
- break;
- default:
- super.handleMessage(msg);
- break;
- }
- }
- };
-
- private Listener mListener = new Listener();
- private EmailAddressAdapter mAddressAdapter;
- private Validator mAddressValidator;
-
- /**
- * Encapsulates known information about a single attachment.
- */
- private static class Attachment implements Serializable {
- public String name;
- public String contentType;
- public long size;
- public Uri uri;
- }
-
- /**
- * Compose a new message using the given account. If account is null the default account
- * will be used.
- * @param context
- * @param account
- */
- public static void actionCompose(Context context, Account account) {
- try {
- Intent i = new Intent(context, MessageCompose.class);
- i.putExtra(EXTRA_ACCOUNT, account);
- context.startActivity(i);
- } catch (ActivityNotFoundException anfe) {
- // Swallow it - this is usually a race condition, especially under automated test.
- // (The message composer might have been disabled)
- if (Config.LOGD) {
- Log.d(Email.LOG_TAG, anfe.toString());
- }
- }
- }
-
- /**
- * Compose a new message as a reply to the given message. If replyAll is true the function
- * is reply all instead of simply reply.
- * @param context
- * @param account
- * @param message
- * @param replyAll
- */
- public static void actionReply(
- Context context,
- Account account,
- Message message,
- boolean replyAll) {
- Intent i = new Intent(context, MessageCompose.class);
- i.putExtra(EXTRA_ACCOUNT, account);
- i.putExtra(EXTRA_FOLDER, message.getFolder().getName());
- i.putExtra(EXTRA_MESSAGE, message.getUid());
- if (replyAll) {
- i.setAction(ACTION_REPLY_ALL);
- }
- else {
- i.setAction(ACTION_REPLY);
- }
- context.startActivity(i);
- }
-
- /**
- * Compose a new message as a forward of the given message.
- * @param context
- * @param account
- * @param message
- */
- public static void actionForward(Context context, Account account, Message message) {
- Intent i = new Intent(context, MessageCompose.class);
- i.putExtra(EXTRA_ACCOUNT, account);
- i.putExtra(EXTRA_FOLDER, message.getFolder().getName());
- i.putExtra(EXTRA_MESSAGE, message.getUid());
- i.setAction(ACTION_FORWARD);
- context.startActivity(i);
- }
-
- /**
- * Continue composition of the given message. This action modifies the way this Activity
- * handles certain actions.
- * Save will attempt to replace the message in the given folder with the updated version.
- * Discard will delete the message from the given folder.
- * @param context
- * @param account
- * @param message
- */
- public static void actionEditDraft(Context context, Account account, Message message) {
- Intent i = new Intent(context, MessageCompose.class);
- i.putExtra(EXTRA_ACCOUNT, account);
- i.putExtra(EXTRA_FOLDER, message.getFolder().getName());
- i.putExtra(EXTRA_MESSAGE, message.getUid());
- i.setAction(ACTION_EDIT_DRAFT);
- context.startActivity(i);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
-
- setContentView(R.layout.message_compose);
-
- mAddressAdapter = new EmailAddressAdapter(this);
- mAddressValidator = new EmailAddressValidator();
-
- mToView = (MultiAutoCompleteTextView)findViewById(R.id.to);
- mCcView = (MultiAutoCompleteTextView)findViewById(R.id.cc);
- mBccView = (MultiAutoCompleteTextView)findViewById(R.id.bcc);
- mSubjectView = (EditText)findViewById(R.id.subject);
- mMessageContentView = (EditText)findViewById(R.id.message_content);
- mSendButton = (Button)findViewById(R.id.send);
- mDiscardButton = (Button)findViewById(R.id.discard);
- mSaveButton = (Button)findViewById(R.id.save);
- mAttachments = (LinearLayout)findViewById(R.id.attachments);
- mQuotedTextBar = findViewById(R.id.quoted_text_bar);
- mQuotedTextDelete = (ImageButton)findViewById(R.id.quoted_text_delete);
- mQuotedText = (WebView)findViewById(R.id.quoted_text);
-
- TextWatcher watcher = new TextWatcher() {
- public void beforeTextChanged(CharSequence s, int start,
- int before, int after) { }
-
- public void onTextChanged(CharSequence s, int start,
- int before, int count) {
- mDraftNeedsSaving = true;
- }
-
- public void afterTextChanged(android.text.Editable s) { }
- };
-
- /**
- * Implements special address cleanup rules:
- * The first space key entry following an "@" symbol that is followed by any combination
- * of letters and symbols, including one+ dots and zero commas, should insert an extra
- * comma (followed by the space).
- */
- InputFilter recipientFilter = new InputFilter() {
-
- public CharSequence filter(CharSequence source, int start, int end, Spanned dest,
- int dstart, int dend) {
-
- // quick check - did they enter a single space?
- if (end-start != 1 || source.charAt(start) != ' ') {
- return null;
- }
-
- // determine if the characters before the new space fit the pattern
- // follow backwards and see if we find a comma, dot, or @
- int scanBack = dstart;
- boolean dotFound = false;
- while (scanBack > 0) {
- char c = dest.charAt(--scanBack);
- switch (c) {
- case '.':
- dotFound = true; // one or more dots are req'd
- break;
- case ',':
- return null;
- case '@':
- if (!dotFound) {
- return null;
- }
- // we have found a comma-insert case. now just do it
- // in the least expensive way we can.
- if (source instanceof Spanned) {
- SpannableStringBuilder sb = new SpannableStringBuilder(",");
- sb.append(source);
- return sb;
- } else {
- return ", ";
- }
- default:
- // just keep going
- }
- }
-
- // no termination cases were found, so don't edit the input
- return null;
- }
- };
- InputFilter[] recipientFilters = new InputFilter[] { recipientFilter };
-
- mToView.addTextChangedListener(watcher);
- mCcView.addTextChangedListener(watcher);
- mBccView.addTextChangedListener(watcher);
- mSubjectView.addTextChangedListener(watcher);
- mMessageContentView.addTextChangedListener(watcher);
-
- // NOTE: assumes no other filters are set
- mToView.setFilters(recipientFilters);
- mCcView.setFilters(recipientFilters);
- mBccView.setFilters(recipientFilters);
-
- /*
- * We set this to invisible by default. Other methods will turn it back on if it's
- * needed.
- */
- mQuotedTextBar.setVisibility(View.GONE);
- mQuotedText.setVisibility(View.GONE);
-
- mQuotedTextDelete.setOnClickListener(this);
-
- mToView.setAdapter(mAddressAdapter);
- mToView.setTokenizer(new Rfc822Tokenizer());
- mToView.setValidator(mAddressValidator);
-
- mCcView.setAdapter(mAddressAdapter);
- mCcView.setTokenizer(new Rfc822Tokenizer());
- mCcView.setValidator(mAddressValidator);
-
- mBccView.setAdapter(mAddressAdapter);
- mBccView.setTokenizer(new Rfc822Tokenizer());
- mBccView.setValidator(mAddressValidator);
-
- mSendButton.setOnClickListener(this);
- mDiscardButton.setOnClickListener(this);
- mSaveButton.setOnClickListener(this);
-
- mSubjectView.setOnFocusChangeListener(this);
-
- if (savedInstanceState != null) {
- /*
- * This data gets used in onCreate, so grab it here instead of onRestoreIntstanceState
- */
- mSourceMessageProcessed =
- savedInstanceState.getBoolean(STATE_KEY_SOURCE_MESSAGE_PROCED, false);
- }
-
- Intent intent = getIntent();
-
- String action = intent.getAction();
-
- // Handle the various intents that launch the message composer
- if (Intent.ACTION_VIEW.equals(action) || Intent.ACTION_SENDTO.equals(action) ||
- (Intent.ACTION_SEND.equals(action))) {
-
- // Check first for a valid account
- mAccount = Preferences.getPreferences(this).getDefaultAccount();
- if (mAccount == null) {
- // There are no accounts set up. This should not have happened. Prompt the
- // user to set up an account as an acceptable bailout.
- Accounts.actionShowAccounts(this);
- mDraftNeedsSaving = false;
- finish();
- return;
- }
-
- // Use the fields found in the Intent to prefill as much of the message as possible
- initFromIntent(intent);
- }
- else {
- // Otherwise, handle the internal cases (Message Composer invoked from within app)
- mAccount = (Account) intent.getSerializableExtra(EXTRA_ACCOUNT);
- mFolder = intent.getStringExtra(EXTRA_FOLDER);
- mSourceMessageUid = intent.getStringExtra(EXTRA_MESSAGE);
- }
-
- if (ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action) ||
- ACTION_FORWARD.equals(action) || ACTION_EDIT_DRAFT.equals(action)) {
- /*
- * If we need to load the message we add ourself as a message listener here
- * so we can kick it off. Normally we add in onResume but we don't
- * want to reload the message every time the activity is resumed.
- * There is no harm in adding twice.
- */
- MessagingController.getInstance(getApplication()).addListener(mListener);
- MessagingController.getInstance(getApplication()).loadMessageForView(
- mAccount,
- mFolder,
- mSourceMessageUid,
- mListener);
- }
-
- updateTitle();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- MessagingController.getInstance(getApplication()).addListener(mListener);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- saveIfNeeded();
- MessagingController.getInstance(getApplication()).removeListener(mListener);
- }
-
- /**
- * We override onDestroy to make sure that the WebView gets explicitly destroyed.
- * Otherwise it can leak native references.
- */
- @Override
- public void onDestroy() {
- super.onDestroy();
- mQuotedText.destroy();
- mQuotedText = null;
- }
-
- /**
- * The framework handles most of the fields, but we need to handle stuff that we
- * dynamically show and hide:
- * Attachment list,
- * Cc field,
- * Bcc field,
- * Quoted text,
- */
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- saveIfNeeded();
- ArrayList<Uri> attachments = new ArrayList<Uri>();
- for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
- View view = mAttachments.getChildAt(i);
- Attachment attachment = (Attachment) view.getTag();
- attachments.add(attachment.uri);
- }
- outState.putParcelableArrayList(STATE_KEY_ATTACHMENTS, attachments);
- outState.putBoolean(STATE_KEY_CC_SHOWN, mCcView.getVisibility() == View.VISIBLE);
- outState.putBoolean(STATE_KEY_BCC_SHOWN, mBccView.getVisibility() == View.VISIBLE);
- outState.putBoolean(STATE_KEY_QUOTED_TEXT_SHOWN,
- mQuotedTextBar.getVisibility() == View.VISIBLE);
- outState.putBoolean(STATE_KEY_SOURCE_MESSAGE_PROCED, mSourceMessageProcessed);
- outState.putString(STATE_KEY_DRAFT_UID, mDraftUid);
- }
-
- @Override
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- ArrayList<Parcelable> attachments =
- savedInstanceState.getParcelableArrayList(STATE_KEY_ATTACHMENTS);
- mAttachments.removeAllViews();
- for (Parcelable p : attachments) {
- Uri uri = (Uri) p;
- addAttachment(uri);
- }
-
- mCcView.setVisibility(savedInstanceState.getBoolean(STATE_KEY_CC_SHOWN) ?
- View.VISIBLE : View.GONE);
- mBccView.setVisibility(savedInstanceState.getBoolean(STATE_KEY_BCC_SHOWN) ?
- View.VISIBLE : View.GONE);
- mQuotedTextBar.setVisibility(savedInstanceState.getBoolean(STATE_KEY_QUOTED_TEXT_SHOWN) ?
- View.VISIBLE : View.GONE);
- mQuotedText.setVisibility(savedInstanceState.getBoolean(STATE_KEY_QUOTED_TEXT_SHOWN) ?
- View.VISIBLE : View.GONE);
- mDraftUid = savedInstanceState.getString(STATE_KEY_DRAFT_UID);
- mDraftNeedsSaving = false;
- }
-
- private void updateTitle() {
- if (mSubjectView.getText().length() == 0) {
- setTitle(R.string.compose_title);
- } else {
- setTitle(mSubjectView.getText().toString());
- }
- }
-
- public void onFocusChange(View view, boolean focused) {
- if (!focused) {
- updateTitle();
- }
- }
-
- private void addAddresses(MultiAutoCompleteTextView view, Address[] addresses) {
- if (addresses == null) {
- return;
- }
- for (Address address : addresses) {
- addAddress(view, address.toString());
- }
- }
-
- private void addAddresses(MultiAutoCompleteTextView view, String[] addresses) {
- if (addresses == null) {
- return;
- }
- for (String oneAddress : addresses) {
- addAddress(view, oneAddress);
- }
- }
-
- private void addAddress(MultiAutoCompleteTextView view, String address) {
- view.append(address + ", ");
- }
-
- private Address[] getAddresses(MultiAutoCompleteTextView view) {
- Address[] addresses = Address.parse(view.getText().toString().trim());
- return addresses;
- }
-
- private MimeMessage createMessage() throws MessagingException {
- MimeMessage message = new MimeMessage();
- message.setSentDate(new Date());
- Address from = new Address(mAccount.getEmail(), mAccount.getName());
- message.setFrom(from);
- message.setRecipients(RecipientType.TO, getAddresses(mToView));
- message.setRecipients(RecipientType.CC, getAddresses(mCcView));
- message.setRecipients(RecipientType.BCC, getAddresses(mBccView));
- message.setSubject(mSubjectView.getText().toString());
-
- /*
- * Build the Body that will contain the text of the message. We'll decide where to
- * include it later.
- */
-
- String text = mMessageContentView.getText().toString();
-
- if (mQuotedTextBar.getVisibility() == View.VISIBLE) {
- String action = getIntent().getAction();
- String quotedText = null;
- Part part = MimeUtility.findFirstPartByMimeType(mSourceMessage,
- "text/plain");
- if (part != null) {
- quotedText = MimeUtility.getTextFromPart(part);
- }
- if (ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action)) {
- text += String.format(
- getString(R.string.message_compose_reply_header_fmt),
- Address.toString(mSourceMessage.getFrom()));
- if (quotedText != null) {
- text += quotedText.replaceAll("(?m)^", ">");
- }
- }
- else if (ACTION_FORWARD.equals(action)) {
- text += String.format(
- getString(R.string.message_compose_fwd_header_fmt),
- mSourceMessage.getSubject(),
- Address.toString(mSourceMessage.getFrom()),
- Address.toString(
- mSourceMessage.getRecipients(RecipientType.TO)),
- Address.toString(
- mSourceMessage.getRecipients(RecipientType.CC)));
- if (quotedText != null) {
- text += quotedText;
- }
- }
- }
-
- TextBody body = new TextBody(text);
-
- if (mAttachments.getChildCount() > 0) {
- /*
- * The message has attachments that need to be included. First we add the part
- * containing the text that will be sent and then we include each attachment.
- */
-
- MimeMultipart mp;
-
- mp = new MimeMultipart();
- mp.addBodyPart(new MimeBodyPart(body, "text/plain"));
-
- for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
- Attachment attachment = (Attachment) mAttachments.getChildAt(i).getTag();
- MimeBodyPart bp = new MimeBodyPart(
- new LocalStore.LocalAttachmentBody(attachment.uri, getApplication()));
- bp.setHeader(MimeHeader.HEADER_CONTENT_TYPE, String.format("%s;\n name=\"%s\"",
- attachment.contentType,
- attachment.name));
- bp.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64");
- bp.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION,
- String.format("attachment;\n filename=\"%s\"",
- attachment.name));
- mp.addBodyPart(bp);
- }
-
- message.setBody(mp);
- }
- else {
- /*
- * No attachments to include, just stick the text body in the message and call
- * it good.
- */
- message.setBody(body);
- }
-
- return message;
- }
-
- private void sendOrSaveMessage(boolean save) {
- /*
- * Create the message from all the data the user has entered.
- */
- MimeMessage message;
- try {
- message = createMessage();
- }
- catch (MessagingException me) {
- Log.e(Email.LOG_TAG, "Failed to create new message for send or save.", me);
- throw new RuntimeException("Failed to create a new message for send or save.", me);
- }
-
- if (save) {
- /*
- * Save a draft
- */
- if (mDraftUid != null) {
- message.setUid(mDraftUid);
- }
- else if (ACTION_EDIT_DRAFT.equals(getIntent().getAction())) {
- /*
- * We're saving a previously saved draft, so update the new message's uid
- * to the old message's uid.
- */
- message.setUid(mSourceMessageUid);
- }
- MessagingController.getInstance(getApplication()).saveDraft(mAccount, message);
- mDraftUid = message.getUid();
-
- // Don't display the toast if the user is just changing the orientation
- if ((getChangingConfigurations() & ActivityInfo.CONFIG_ORIENTATION) == 0) {
- mHandler.sendEmptyMessage(MSG_SAVED_DRAFT);
- }
- }
- else {
- /*
- * Send the message
- * TODO Is it possible for us to be editing a draft with a null source message? Don't
- * think so. Could probably remove below check.
- */
- if (ACTION_EDIT_DRAFT.equals(getIntent().getAction())
- && mSourceMessageUid != null) {
- /*
- * We're sending a previously saved draft, so delete the old draft first.
- */
- MessagingController.getInstance(getApplication()).deleteMessage(
- mAccount,
- mFolder,
- mSourceMessage,
- null);
- }
- MessagingController.getInstance(getApplication()).sendMessage(mAccount, message, null);
- }
- }
-
- private void saveIfNeeded() {
- if (!mDraftNeedsSaving) {
- return;
- }
- mDraftNeedsSaving = false;
- sendOrSaveMessage(true);
- }
-
- private void onSend() {
- if (getAddresses(mToView).length == 0 &&
- getAddresses(mCcView).length == 0 &&
- getAddresses(mBccView).length == 0) {
- mToView.setError(getString(R.string.message_compose_error_no_recipients));
- Toast.makeText(this, getString(R.string.message_compose_error_no_recipients),
- Toast.LENGTH_LONG).show();
- return;
- }
- sendOrSaveMessage(false);
- mDraftNeedsSaving = false;
- finish();
- }
-
- private void onDiscard() {
- if (mSourceMessageUid != null) {
- if (ACTION_EDIT_DRAFT.equals(getIntent().getAction()) && mSourceMessageUid != null) {
- MessagingController.getInstance(getApplication()).deleteMessage(
- mAccount,
- mFolder,
- mSourceMessage,
- null);
- }
- }
- mHandler.sendEmptyMessage(MSG_DISCARDED_DRAFT);
- mDraftNeedsSaving = false;
- finish();
- }
-
- private void onSave() {
- saveIfNeeded();
- finish();
- }
-
- private void onAddCcBcc() {
- mCcView.setVisibility(View.VISIBLE);
- mBccView.setVisibility(View.VISIBLE);
- }
-
- /**
- * Kick off a picker for whatever kind of MIME types we'll accept and let Android take over.
- */
- private void onAddAttachment() {
- Intent i = new Intent(Intent.ACTION_GET_CONTENT);
- i.addCategory(Intent.CATEGORY_OPENABLE);
- i.setType(Email.ACCEPTABLE_ATTACHMENT_SEND_TYPES[0]);
- startActivityForResult(Intent.createChooser(i, null), ACTIVITY_REQUEST_PICK_ATTACHMENT);
- }
-
- private void addAttachment(Uri uri) {
- addAttachment(uri, -1, null);
- }
-
- private void addAttachment(Uri uri, int size, String name) {
- ContentResolver contentResolver = getContentResolver();
-
- String contentType = contentResolver.getType(uri);
-
- if (contentType == null) {
- contentType = "";
- }
-
- Attachment attachment = new Attachment();
- attachment.name = name;
- attachment.contentType = contentType;
- attachment.size = size;
- attachment.uri = uri;
-
- if (attachment.size == -1 || attachment.name == null) {
- Cursor metadataCursor = contentResolver.query(
- uri,
- new String[]{ OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE },
- null,
- null,
- null);
- if (metadataCursor != null) {
- try {
- if (metadataCursor.moveToFirst()) {
- if (attachment.name == null) {
- attachment.name = metadataCursor.getString(0);
- }
- if (attachment.size == -1) {
- attachment.size = metadataCursor.getInt(1);
- }
- }
- } finally {
- metadataCursor.close();
- }
- }
- }
-
- if (attachment.name == null) {
- attachment.name = uri.getLastPathSegment();
- }
-
- View view = getLayoutInflater().inflate(
- R.layout.message_compose_attachment,
- mAttachments,
- false);
- TextView nameView = (TextView)view.findViewById(R.id.attachment_name);
- ImageButton delete = (ImageButton)view.findViewById(R.id.attachment_delete);
- nameView.setText(attachment.name);
- delete.setOnClickListener(this);
- delete.setTag(view);
- view.setTag(attachment);
- mAttachments.addView(view);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (data == null) {
- return;
- }
- addAttachment(data.getData());
- mDraftNeedsSaving = true;
- }
-
- public void onClick(View view) {
- switch (view.getId()) {
- case R.id.send:
- onSend();
- break;
- case R.id.save:
- onSave();
- break;
- case R.id.discard:
- onDiscard();
- break;
- case R.id.attachment_delete:
- /*
- * The view is the delete button, and we have previously set the tag of
- * the delete button to the view that owns it. We don't use parent because the
- * view is very complex and could change in the future.
- */
- mAttachments.removeView((View) view.getTag());
- mDraftNeedsSaving = true;
- break;
- case R.id.quoted_text_delete:
- mQuotedTextBar.setVisibility(View.GONE);
- mQuotedText.setVisibility(View.GONE);
- mDraftNeedsSaving = true;
- break;
- }
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.send:
- onSend();
- break;
- case R.id.save:
- onSave();
- break;
- case R.id.discard:
- onDiscard();
- break;
- case R.id.add_cc_bcc:
- onAddCcBcc();
- break;
- case R.id.add_attachment:
- onAddAttachment();
- break;
- default:
- return super.onOptionsItemSelected(item);
- }
- return true;
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- getMenuInflater().inflate(R.menu.message_compose_option, menu);
- return true;
- }
-
- /**
- * Returns true if all attachments were able to be attached, otherwise returns false.
- */
- private boolean loadAttachments(Part part, int depth) throws MessagingException {
- if (part.getBody() instanceof Multipart) {
- Multipart mp = (Multipart) part.getBody();
- boolean ret = true;
- for (int i = 0, count = mp.getCount(); i < count; i++) {
- if (!loadAttachments(mp.getBodyPart(i), depth + 1)) {
- ret = false;
- }
- }
- return ret;
- } else {
- String contentType = MimeUtility.unfoldAndDecode(part.getContentType());
- String name = MimeUtility.getHeaderParameter(contentType, "name");
- if (name != null) {
- Body body = part.getBody();
- if (body != null && body instanceof LocalAttachmentBody) {
- final Uri uri = ((LocalAttachmentBody) body).getContentUri();
- mHandler.post(new Runnable() {
- public void run() {
- addAttachment(uri);
- }
- });
- }
- else {
- return false;
- }
- }
- return true;
- }
- }
-
- /**
- * Fill all the widgets with the content found in the Intent Extra, if any.
- *
- * Note that we don't actually check the intent action (typically VIEW, SENDTO, or SEND).
- * There is enough overlap in the definitions that it makes more sense to simply check for
- * all available data and use as much of it as possible.
- *
- * With one exception: EXTRA_STREAM is defined as only valid for ACTION_SEND.
- *
- * @param intent the launch intent
- */
- /* package */ void initFromIntent(Intent intent) {
-
- // First, add values stored in top-level extras
-
- String[] extraStrings = intent.getStringArrayExtra(Intent.EXTRA_EMAIL);
- if (extraStrings != null) {
- addAddresses(mToView, extraStrings);
- }
- extraStrings = intent.getStringArrayExtra(Intent.EXTRA_CC);
- if (extraStrings != null) {
- addAddresses(mCcView, extraStrings);
- }
- extraStrings = intent.getStringArrayExtra(Intent.EXTRA_BCC);
- if (extraStrings != null) {
- addAddresses(mBccView, extraStrings);
- }
- String extraString = intent.getStringExtra(Intent.EXTRA_SUBJECT);
- if (extraString != null) {
- mSubjectView.setText(extraString);
- }
-
- // Next, if we were invoked with a URI, try to interpret it
- // We'll take two courses here. If it's mailto:, there is a specific set of rules
- // that define various optional fields. However, for any other scheme, we'll simply
- // take the entire scheme-specific part and interpret it as a possible list of addresses.
-
- final Uri dataUri = intent.getData();
- if (dataUri != null) {
- if ("mailto".equals(dataUri.getScheme())) {
- initializeFromMailTo(dataUri.toString());
- } else {
- String toText = dataUri.getSchemeSpecificPart();
- if (toText != null) {
- addAddresses(mToView, toText.split(","));
- }
- }
- }
-
- // Next, fill in the plaintext (note, this will override mailto:?body=)
-
- CharSequence text = intent.getCharSequenceExtra(Intent.EXTRA_TEXT);
- if (text != null) {
- mMessageContentView.setText(text);
- }
-
- // Next, convert EXTRA_STREAM into an attachment
-
- if (Intent.ACTION_SEND.equals(intent.getAction()) && intent.hasExtra(Intent.EXTRA_STREAM)) {
- String type = intent.getType();
- Uri stream = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
- if (stream != null && type != null) {
- if (MimeUtility.mimeTypeMatches(type, Email.ACCEPTABLE_ATTACHMENT_SEND_TYPES)) {
- addAttachment(stream);
- }
- }
- }
-
- // Finally - expose fields that were filled in but are normally hidden, and set focus
-
- if (mCcView.length() > 0) {
- mCcView.setVisibility(View.VISIBLE);
- }
- if (mBccView.length() > 0) {
- mBccView.setVisibility(View.VISIBLE);
- }
- setNewMessageFocus();
- mDraftNeedsSaving = false;
- }
-
- /**
- * When we are launched with an intent that includes a mailto: URI, we can actually
- * gather quite a few of our message fields from it.
- *
- * @mailToString the href (which must start with "mailto:").
- */
- private void initializeFromMailTo(String mailToString) {
-
- // Chop up everything between mailto: and ? to find recipients
- int index = mailToString.indexOf("?");
- int length = "mailto".length() + 1;
- String to;
- try {
- // Extract the recipient after mailto:
- if (index == -1) {
- to = decode(mailToString.substring(length));
- } else {
- to = decode(mailToString.substring(length, index));
- }
- addAddresses(mToView, to.split(" ,"));
- } catch (UnsupportedEncodingException e) {
- Log.e(Email.LOG_TAG, e.getMessage() + " while decoding '" + mailToString + "'");
- }
-
- // Extract the other parameters
-
- // We need to disguise this string as a URI in order to parse it
- Uri uri = Uri.parse("foo://" + mailToString);
-
- List<String> cc = uri.getQueryParameters("cc");
- addAddresses(mCcView, cc.toArray(new String[cc.size()]));
-
- List<String> otherTo = uri.getQueryParameters("to");
- addAddresses(mCcView, otherTo.toArray(new String[otherTo.size()]));
-
- List<String> bcc = uri.getQueryParameters("bcc");
- addAddresses(mBccView, bcc.toArray(new String[bcc.size()]));
-
- List<String> subject = uri.getQueryParameters("subject");
- if (subject.size() > 0) {
- mSubjectView.setText(subject.get(0));
- }
-
- List<String> body = uri.getQueryParameters("body");
- if (body.size() > 0) {
- mMessageContentView.setText(body.get(0));
- }
- }
-
- private String decode(String s) throws UnsupportedEncodingException {
- return URLDecoder.decode(s, "UTF-8");
- }
-
- /**
- * Pull out the parts of the now loaded source message and apply them to the new message
- * depending on the type of message being composed.
- * @param message
- */
- /* package */ /**
- * @param message
- */
- void processSourceMessage(Message message) {
- String action = getIntent().getAction();
- if (ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action)) {
- try {
- if (message.getSubject() != null &&
- !message.getSubject().toLowerCase().startsWith("re:")) {
- mSubjectView.setText("Re: " + message.getSubject());
- }
- else {
- mSubjectView.setText(message.getSubject());
- }
- /*
- * If a reply-to was included with the message use that, otherwise use the from
- * or sender address.
- */
- Address[] replyToAddresses;
- if (message.getReplyTo().length > 0) {
- addAddresses(mToView, replyToAddresses = message.getReplyTo());
- }
- else {
- addAddresses(mToView, replyToAddresses = message.getFrom());
- }
- if (ACTION_REPLY_ALL.equals(action)) {
- for (Address address : message.getRecipients(RecipientType.TO)) {
- if (!address.getAddress().equalsIgnoreCase(mAccount.getEmail())) {
- addAddress(mToView, address.toString());
- }
- }
- if (message.getRecipients(RecipientType.CC).length > 0) {
- for (Address address : message.getRecipients(RecipientType.CC)) {
- if (!Utility.arrayContains(replyToAddresses, address)) {
- addAddress(mCcView, address.toString());
- }
- }
- mCcView.setVisibility(View.VISIBLE);
- }
- }
-
- Part part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
- if (part == null) {
- part = MimeUtility.findFirstPartByMimeType(message, "text/html");
- }
- if (part != null) {
- String text = MimeUtility.getTextFromPart(part);
- if (text != null) {
- mQuotedTextBar.setVisibility(View.VISIBLE);
- mQuotedText.setVisibility(View.VISIBLE);
- mQuotedText.loadDataWithBaseURL("email://", text, part.getMimeType(),
- "utf-8", null);
- }
- }
- }
- catch (MessagingException me) {
- /*
- * This really should not happen at this point but if it does it's okay.
- * The user can continue composing their message.
- */
- }
- }
- else if (ACTION_FORWARD.equals(action)) {
- try {
- if (message.getSubject() != null &&
- !message.getSubject().toLowerCase().startsWith("fwd:")) {
- mSubjectView.setText("Fwd: " + message.getSubject());
- }
- else {
- mSubjectView.setText(message.getSubject());
- }
-
- Part part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
- if (part == null) {
- part = MimeUtility.findFirstPartByMimeType(message, "text/html");
- }
- if (part != null) {
- String text = MimeUtility.getTextFromPart(part);
- if (text != null) {
- mQuotedTextBar.setVisibility(View.VISIBLE);
- mQuotedText.setVisibility(View.VISIBLE);
- mQuotedText.loadDataWithBaseURL("email://", text, part.getMimeType(),
- "utf-8", null);
- }
- }
- if (!mSourceMessageProcessed) {
- if (!loadAttachments(message, 0)) {
- mHandler.sendEmptyMessage(MSG_SKIPPED_ATTACHMENTS);
- }
- }
- }
- catch (MessagingException me) {
- /*
- * This really should not happen at this point but if it does it's okay.
- * The user can continue composing their message.
- */
- }
- }
- else if (ACTION_EDIT_DRAFT.equals(action)) {
- try {
- mSubjectView.setText(message.getSubject());
- addAddresses(mToView, message.getRecipients(RecipientType.TO));
- if (message.getRecipients(RecipientType.CC).length > 0) {
- addAddresses(mCcView, message.getRecipients(RecipientType.CC));
- mCcView.setVisibility(View.VISIBLE);
- }
- if (message.getRecipients(RecipientType.BCC).length > 0) {
- addAddresses(mBccView, message.getRecipients(RecipientType.BCC));
- mBccView.setVisibility(View.VISIBLE);
- }
- Part part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
- if (part != null) {
- String text = MimeUtility.getTextFromPart(part);
- mMessageContentView.setText(text);
- }
- if (!mSourceMessageProcessed) {
- loadAttachments(message, 0);
- }
- }
- catch (MessagingException me) {
- // TODO
- }
- }
-
- setNewMessageFocus();
-
- mSourceMessageProcessed = true;
- mDraftNeedsSaving = false;
- }
-
- /**
- * In order to accelerate typing, position the cursor in the first empty field,
- * or at the end of the body composition field if none are empty. Typically, this will
- * play out as follows:
- * Reply / Reply All - put cursor in the empty message body
- * Forward - put cursor in the empty To field
- * Edit Draft - put cursor in whatever field still needs entry
- */
- private void setNewMessageFocus() {
- if (mToView.length() == 0) {
- mToView.requestFocus();
- } else if (mSubjectView.length() == 0) {
- mSubjectView.requestFocus();
- } else {
- mMessageContentView.requestFocus();
- // when selecting the message content, explicitly move IP to the end, so you can
- // quickly resume typing into a draft
- int selection = mMessageContentView.length();
- mMessageContentView.setSelection(selection, selection);
- }
- }
-
- class Listener extends MessagingListener {
- @Override
- public void loadMessageForViewStarted(Account account, String folder, String uid) {
- mHandler.sendEmptyMessage(MSG_PROGRESS_ON);
- }
-
- @Override
- public void loadMessageForViewFinished(Account account, String folder, String uid,
- Message message) {
- mHandler.sendEmptyMessage(MSG_PROGRESS_OFF);
- }
-
- @Override
- public void loadMessageForViewBodyAvailable(Account account, String folder, String uid,
- final Message message) {
- mSourceMessage = message;
- runOnUiThread(new Runnable() {
- public void run() {
- processSourceMessage(message);
- }
- });
- }
-
- @Override
- public void loadMessageForViewFailed(Account account, String folder, String uid,
- final String message) {
- mHandler.sendEmptyMessage(MSG_PROGRESS_OFF);
- // TODO show network error
- }
-
- @Override
- public void messageUidChanged(
- Account account,
- String folder,
- String oldUid,
- String newUid) {
- if (account.equals(mAccount)
- && (folder.equals(mFolder)
- || (mFolder == null
- && folder.equals(mAccount.getDraftsFolderName())))) {
- if (oldUid.equals(mDraftUid)) {
- mDraftUid = newUid;
- }
- if (oldUid.equals(mSourceMessageUid)) {
- mSourceMessageUid = newUid;
- }
- if (mSourceMessage != null && (oldUid.equals(mSourceMessage.getUid()))) {
- mSourceMessage.setUid(newUid);
- }
- }
- }
- }
-}
diff --git a/src/com/android/email/activity/MessageView.java b/src/com/android/email/activity/MessageView.java
deleted file mode 100644
index 359a03578..000000000
--- a/src/com/android/email/activity/MessageView.java
+++ /dev/null
@@ -1,950 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Map;
-import java.util.regex.Matcher;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.media.MediaScannerConnection;
-import android.media.MediaScannerConnection.MediaScannerConnectionClient;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.Handler;
-import android.os.Process;
-import android.text.util.Regex;
-import android.util.Config;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.Window;
-import android.view.View.OnClickListener;
-import android.webkit.CacheManager;
-import android.webkit.UrlInterceptHandler;
-import android.webkit.WebView;
-import android.webkit.CacheManager.CacheResult;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import org.apache.commons.io.IOUtils;
-
-import com.android.email.Account;
-import com.android.email.Email;
-import com.android.email.MessagingController;
-import com.android.email.MessagingListener;
-import com.android.email.R;
-import com.android.email.Utility;
-import com.android.email.mail.Address;
-import com.android.email.mail.Message;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Multipart;
-import com.android.email.mail.Part;
-import com.android.email.mail.Message.RecipientType;
-import com.android.email.mail.internet.MimeUtility;
-import com.android.email.mail.store.LocalStore.LocalAttachmentBodyPart;
-import com.android.email.mail.store.LocalStore.LocalMessage;
-import com.android.email.provider.AttachmentProvider;
-
-public class MessageView extends Activity
- implements UrlInterceptHandler, OnClickListener {
- private static final String EXTRA_ACCOUNT = "com.android.email.MessageView_account";
- private static final String EXTRA_FOLDER = "com.android.email.MessageView_folder";
- private static final String EXTRA_MESSAGE = "com.android.email.MessageView_message";
- private static final String EXTRA_FOLDER_UIDS = "com.android.email.MessageView_folderUids";
- private static final String EXTRA_NEXT = "com.android.email.MessageView_next";
-
- private TextView mSubjectView;
- private TextView mFromView;
- private TextView mDateView;
- private TextView mTimeView;
- private TextView mToView;
- private TextView mCcView;
- private View mCcContainerView;
- private WebView mMessageContentView;
- private LinearLayout mAttachments;
- private View mAttachmentIcon;
- private View mShowPicturesSection;
-
- private Account mAccount;
- private String mFolder;
- private String mMessageUid;
- private ArrayList<String> mFolderUids;
-
- private Message mMessage;
- private String mNextMessageUid = null;
- private String mPreviousMessageUid = null;
-
- private java.text.DateFormat mDateFormat;
- private java.text.DateFormat mTimeFormat;
-
- private Listener mListener = new Listener();
- private MessageViewHandler mHandler = new MessageViewHandler();
-
- class MessageViewHandler extends Handler {
- private static final int MSG_PROGRESS = 2;
- private static final int MSG_ADD_ATTACHMENT = 3;
- private static final int MSG_SET_ATTACHMENTS_ENABLED = 4;
- private static final int MSG_SET_HEADERS = 5;
- private static final int MSG_NETWORK_ERROR = 6;
- private static final int MSG_ATTACHMENT_SAVED = 7;
- private static final int MSG_ATTACHMENT_NOT_SAVED = 8;
- private static final int MSG_SHOW_SHOW_PICTURES = 9;
- private static final int MSG_FETCHING_ATTACHMENT = 10;
-
- @Override
- public void handleMessage(android.os.Message msg) {
- switch (msg.what) {
- case MSG_PROGRESS:
- setProgressBarIndeterminateVisibility(msg.arg1 != 0);
- break;
- case MSG_ADD_ATTACHMENT:
- mAttachments.addView((View) msg.obj);
- mAttachments.setVisibility(View.VISIBLE);
- break;
- case MSG_SET_ATTACHMENTS_ENABLED:
- for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
- Attachment attachment = (Attachment) mAttachments.getChildAt(i).getTag();
- attachment.viewButton.setEnabled(msg.arg1 == 1);
- attachment.downloadButton.setEnabled(msg.arg1 == 1);
- }
- break;
- case MSG_SET_HEADERS:
- String[] values = (String[]) msg.obj;
- mSubjectView.setText(values[0]);
- mFromView.setText(values[1]);
- mTimeView.setText(values[2]);
- mDateView.setText(values[3]);
- mToView.setText(values[4]);
- mCcView.setText(values[5]);
- mCcContainerView.setVisibility((values[5] != null) ? View.VISIBLE : View.GONE);
- mAttachmentIcon.setVisibility(msg.arg1 == 1 ? View.VISIBLE : View.GONE);
- break;
- case MSG_NETWORK_ERROR:
- Toast.makeText(MessageView.this,
- R.string.status_network_error, Toast.LENGTH_LONG).show();
- break;
- case MSG_ATTACHMENT_SAVED:
- Toast.makeText(MessageView.this, String.format(
- getString(R.string.message_view_status_attachment_saved), msg.obj),
- Toast.LENGTH_LONG).show();
- break;
- case MSG_ATTACHMENT_NOT_SAVED:
- Toast.makeText(MessageView.this,
- getString(R.string.message_view_status_attachment_not_saved),
- Toast.LENGTH_LONG).show();
- break;
- case MSG_SHOW_SHOW_PICTURES:
- mShowPicturesSection.setVisibility(msg.arg1 == 1 ? View.VISIBLE : View.GONE);
- break;
- case MSG_FETCHING_ATTACHMENT:
- Toast.makeText(MessageView.this,
- getString(R.string.message_view_fetching_attachment_toast),
- Toast.LENGTH_SHORT).show();
- break;
- default:
- super.handleMessage(msg);
- }
- }
-
- public void progress(boolean progress) {
- android.os.Message msg = new android.os.Message();
- msg.what = MSG_PROGRESS;
- msg.arg1 = progress ? 1 : 0;
- sendMessage(msg);
- }
-
- public void addAttachment(View attachmentView) {
- android.os.Message msg = new android.os.Message();
- msg.what = MSG_ADD_ATTACHMENT;
- msg.obj = attachmentView;
- sendMessage(msg);
- }
-
- public void setAttachmentsEnabled(boolean enabled) {
- android.os.Message msg = new android.os.Message();
- msg.what = MSG_SET_ATTACHMENTS_ENABLED;
- msg.arg1 = enabled ? 1 : 0;
- sendMessage(msg);
- }
-
- public void setHeaders(
- String subject,
- String from,
- String time,
- String date,
- String to,
- String cc,
- boolean hasAttachments) {
- android.os.Message msg = new android.os.Message();
- msg.what = MSG_SET_HEADERS;
- msg.arg1 = hasAttachments ? 1 : 0;
- msg.obj = new String[] { subject, from, time, date, to, cc };
- sendMessage(msg);
- }
-
- public void networkError() {
- sendEmptyMessage(MSG_NETWORK_ERROR);
- }
-
- public void attachmentSaved(String filename) {
- android.os.Message msg = new android.os.Message();
- msg.what = MSG_ATTACHMENT_SAVED;
- msg.obj = filename;
- sendMessage(msg);
- }
-
- public void attachmentNotSaved() {
- sendEmptyMessage(MSG_ATTACHMENT_NOT_SAVED);
- }
-
- public void fetchingAttachment() {
- sendEmptyMessage(MSG_FETCHING_ATTACHMENT);
- }
-
- public void showShowPictures(boolean show) {
- android.os.Message msg = new android.os.Message();
- msg.what = MSG_SHOW_SHOW_PICTURES;
- msg.arg1 = show ? 1 : 0;
- sendMessage(msg);
- }
- }
-
- /**
- * Encapsulates known information about a single attachment.
- */
- private static class Attachment {
- public String name;
- public String contentType;
- public long size;
- public LocalAttachmentBodyPart part;
- public Button viewButton;
- public Button downloadButton;
- public ImageView iconView;
- }
-
- public static void actionView(Context context, Account account,
- String folder, String messageUid, ArrayList<String> folderUids) {
- actionView(context, account, folder, messageUid, folderUids, null);
- }
-
- public static void actionView(Context context, Account account,
- String folder, String messageUid, ArrayList<String> folderUids, Bundle extras) {
- Intent i = new Intent(context, MessageView.class);
- i.putExtra(EXTRA_ACCOUNT, account);
- i.putExtra(EXTRA_FOLDER, folder);
- i.putExtra(EXTRA_MESSAGE, messageUid);
- i.putExtra(EXTRA_FOLDER_UIDS, folderUids);
- if (extras != null) {
- i.putExtras(extras);
- }
- context.startActivity(i);
- }
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
-
- setContentView(R.layout.message_view);
-
- mSubjectView = (TextView)findViewById(R.id.subject);
- mFromView = (TextView)findViewById(R.id.from);
- mToView = (TextView)findViewById(R.id.to);
- mCcView = (TextView)findViewById(R.id.cc);
- mCcContainerView = findViewById(R.id.cc_container);
- mDateView = (TextView)findViewById(R.id.date);
- mTimeView = (TextView)findViewById(R.id.time);
- mMessageContentView = (WebView)findViewById(R.id.message_content);
- mAttachments = (LinearLayout)findViewById(R.id.attachments);
- mAttachmentIcon = findViewById(R.id.attachment);
- mShowPicturesSection = findViewById(R.id.show_pictures_section);
-
- mMessageContentView.setVerticalScrollBarEnabled(false);
- mAttachments.setVisibility(View.GONE);
- mAttachmentIcon.setVisibility(View.GONE);
-
- findViewById(R.id.reply).setOnClickListener(this);
- findViewById(R.id.reply_all).setOnClickListener(this);
- findViewById(R.id.delete).setOnClickListener(this);
- findViewById(R.id.show_pictures).setOnClickListener(this);
-
- // UrlInterceptRegistry.registerHandler(this);
-
- mMessageContentView.getSettings().setBlockNetworkImage(true);
- mMessageContentView.getSettings().setSupportZoom(false);
-
- setTitle("");
-
- mDateFormat = android.text.format.DateFormat.getDateFormat(this); // short format
- mTimeFormat = android.text.format.DateFormat.getTimeFormat(this); // 12/24 date format
-
- Intent intent = getIntent();
- mAccount = (Account) intent.getSerializableExtra(EXTRA_ACCOUNT);
- mFolder = intent.getStringExtra(EXTRA_FOLDER);
- mMessageUid = intent.getStringExtra(EXTRA_MESSAGE);
- mFolderUids = intent.getStringArrayListExtra(EXTRA_FOLDER_UIDS);
-
- View next = findViewById(R.id.next);
- View previous = findViewById(R.id.previous);
- /*
- * Next and Previous Message are not shown in landscape mode, so
- * we need to check before we use them.
- */
- if (next != null && previous != null) {
- next.setOnClickListener(this);
- previous.setOnClickListener(this);
-
- findSurroundingMessagesUid();
-
- previous.setVisibility(mPreviousMessageUid != null ? View.VISIBLE : View.GONE);
- next.setVisibility(mNextMessageUid != null ? View.VISIBLE : View.GONE);
-
- boolean goNext = intent.getBooleanExtra(EXTRA_NEXT, false);
- if (goNext) {
- next.requestFocus();
- }
- }
-
- MessagingController.getInstance(getApplication()).addListener(mListener);
- new Thread() {
- @Override
- public void run() {
- // TODO this is a spot that should be eventually handled by a MessagingController
- // thread pool. We want it in a thread but it can't be blocked by the normal
- // synchronization stuff in MC.
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- MessagingController.getInstance(getApplication()).loadMessageForView(
- mAccount,
- mFolder,
- mMessageUid,
- mListener);
- }
- }.start();
- }
-
- private void findSurroundingMessagesUid() {
- for (int i = 0, count = mFolderUids.size(); i < count; i++) {
- String messageUid = mFolderUids.get(i);
- if (messageUid.equals(mMessageUid)) {
- if (i != 0) {
- mPreviousMessageUid = mFolderUids.get(i - 1);
- }
-
- if (i != count - 1) {
- mNextMessageUid = mFolderUids.get(i + 1);
- }
- break;
- }
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
- MessagingController.getInstance(getApplication()).addListener(mListener);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- MessagingController.getInstance(getApplication()).removeListener(mListener);
- }
-
- /**
- * We override onDestroy to make sure that the WebView gets explicitly destroyed.
- * Otherwise it can leak native references.
- */
- @Override
- public void onDestroy() {
- super.onDestroy();
- mMessageContentView.destroy();
- mMessageContentView = null;
- }
-
- private void onDelete() {
- if (mMessage != null) {
- MessagingController.getInstance(getApplication()).deleteMessage(
- mAccount,
- mFolder,
- mMessage,
- null);
- Toast.makeText(this, R.string.message_deleted_toast, Toast.LENGTH_SHORT).show();
-
- // Remove this message's Uid locally
- mFolderUids.remove(mMessage.getUid());
- // Check if we have previous/next messages available before choosing
- // which one to display
- findSurroundingMessagesUid();
-
- if (mPreviousMessageUid != null) {
- onPrevious();
- } else if (mNextMessageUid != null) {
- onNext();
- } else {
- finish();
- }
- }
- }
-
- private void onReply() {
- if (mMessage != null) {
- MessageCompose.actionReply(this, mAccount, mMessage, false);
- finish();
- }
- }
-
- private void onReplyAll() {
- if (mMessage != null) {
- MessageCompose.actionReply(this, mAccount, mMessage, true);
- finish();
- }
- }
-
- private void onForward() {
- if (mMessage != null) {
- MessageCompose.actionForward(this, mAccount, mMessage);
- finish();
- }
- }
-
- private void onNext() {
- Bundle extras = new Bundle(1);
- extras.putBoolean(EXTRA_NEXT, true);
- MessageView.actionView(this, mAccount, mFolder, mNextMessageUid, mFolderUids, extras);
- finish();
- }
-
- private void onPrevious() {
- MessageView.actionView(this, mAccount, mFolder, mPreviousMessageUid, mFolderUids);
- finish();
- }
-
- private void onMarkAsUnread() {
- if (mMessage != null) {
- MessagingController.getInstance(getApplication()).markMessageRead(
- mAccount,
- mFolder,
- mMessage.getUid(),
- false);
- }
- }
-
- /**
- * Creates a unique file in the given directory by appending a hyphen
- * and a number to the given filename.
- * @param directory
- * @param filename
- * @return a new File object, or null if one could not be created
- */
- private File createUniqueFile(File directory, String filename) {
- File file = new File(directory, filename);
- if (!file.exists()) {
- return file;
- }
- // Get the extension of the file, if any.
- int index = filename.lastIndexOf('.');
- String format;
- if (index != -1) {
- String name = filename.substring(0, index);
- String extension = filename.substring(index);
- format = name + "-%d" + extension;
- }
- else {
- format = filename + "-%d";
- }
- for (int i = 2; i < Integer.MAX_VALUE; i++) {
- file = new File(directory, String.format(format, i));
- if (!file.exists()) {
- return file;
- }
- }
- return null;
- }
-
- private void onDownloadAttachment(Attachment attachment) {
- if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- /*
- * Abort early if there's no place to save the attachment. We don't want to spend
- * the time downloading it and then abort.
- */
- Toast.makeText(this,
- getString(R.string.message_view_status_attachment_not_saved),
- Toast.LENGTH_SHORT).show();
- return;
- }
- MessagingController.getInstance(getApplication()).loadAttachment(
- mAccount,
- mMessage,
- attachment.part,
- new Object[] { true, attachment },
- mListener);
- }
-
- private void onViewAttachment(Attachment attachment) {
- MessagingController.getInstance(getApplication()).loadAttachment(
- mAccount,
- mMessage,
- attachment.part,
- new Object[] { false, attachment },
- mListener);
- }
-
- private void onShowPictures() {
- if (mMessage != null) {
- mMessageContentView.getSettings().setBlockNetworkImage(false);
- mShowPicturesSection.setVisibility(View.GONE);
- }
- }
-
- public void onClick(View view) {
- switch (view.getId()) {
- case R.id.reply:
- onReply();
- break;
- case R.id.reply_all:
- onReplyAll();
- break;
- case R.id.delete:
- onDelete();
- break;
- case R.id.next:
- onNext();
- break;
- case R.id.previous:
- onPrevious();
- break;
- case R.id.download:
- onDownloadAttachment((Attachment) view.getTag());
- break;
- case R.id.view:
- onViewAttachment((Attachment) view.getTag());
- break;
- case R.id.show_pictures:
- onShowPictures();
- break;
- }
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- boolean handled = handleMenuItem(item.getItemId());
- if (!handled) {
- handled = super.onOptionsItemSelected(item);
- }
- return handled;
- }
-
- /**
- * This is the core functionality of onOptionsItemSelected() but broken out and exposed
- * for testing purposes (because it's annoying to mock a MenuItem).
- *
- * @param menuItemId id that was clicked
- * @return true if handled here
- */
- /* package */ boolean handleMenuItem(int menuItemId) {
- switch (menuItemId) {
- case R.id.delete:
- onDelete();
- break;
- case R.id.reply:
- onReply();
- break;
- case R.id.reply_all:
- onReplyAll();
- break;
- case R.id.forward:
- onForward();
- break;
- case R.id.mark_as_unread:
- onMarkAsUnread();
- break;
- default:
- return false;
- }
- return true;
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- getMenuInflater().inflate(R.menu.message_view_option, menu);
- return true;
- }
-
- public CacheResult service(String url, Map<String, String> headers) {
- String prefix = "http://cid/";
- if (url.startsWith(prefix)) {
- try {
- String contentId = url.substring(prefix.length());
- final Part part = MimeUtility.findPartByContentId(mMessage, "<" + contentId + ">");
- if (part != null) {
- CacheResult cr = new CacheManager.CacheResult();
- // TODO looks fixed in Mainline, cr.setInputStream
- // part.getBody().writeTo(cr.getStream());
- return cr;
- }
- }
- catch (Exception e) {
- // TODO
- }
- }
- return null;
- }
-
- private Bitmap getPreviewIcon(Attachment attachment) {
- try {
- return BitmapFactory.decodeStream(
- getContentResolver().openInputStream(
- AttachmentProvider.getAttachmentThumbnailUri(mAccount,
- attachment.part.getAttachmentId(),
- 62,
- 62)));
- }
- catch (Exception e) {
- /*
- * We don't care what happened, we just return null for the preview icon.
- */
- return null;
- }
- }
-
- /*
- * Formats the given size as a String in bytes, kB, MB or GB with a single digit
- * of precision. Ex: 12,315,000 = 12.3 MB
- */
- public static String formatSize(float size) {
- long kb = 1024;
- long mb = (kb * 1024);
- long gb = (mb * 1024);
- if (size < kb) {
- return String.format("%d bytes", (int) size);
- }
- else if (size < mb) {
- return String.format("%.1f kB", size / kb);
- }
- else if (size < gb) {
- return String.format("%.1f MB", size / mb);
- }
- else {
- return String.format("%.1f GB", size / gb);
- }
- }
-
- private void renderAttachments(Part part, int depth) throws MessagingException {
- String contentType = MimeUtility.unfoldAndDecode(part.getContentType());
- String name = MimeUtility.getHeaderParameter(contentType, "name");
- if (name != null) {
- /*
- * We're guaranteed size because LocalStore.fetch puts it there.
- */
- String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition());
- int size = Integer.parseInt(MimeUtility.getHeaderParameter(contentDisposition, "size"));
-
- Attachment attachment = new Attachment();
- attachment.size = size;
- attachment.contentType = part.getMimeType();
- attachment.name = name;
- attachment.part = (LocalAttachmentBodyPart) part;
-
- LayoutInflater inflater = getLayoutInflater();
- View view = inflater.inflate(R.layout.message_view_attachment, null);
-
- TextView attachmentName = (TextView)view.findViewById(R.id.attachment_name);
- TextView attachmentInfo = (TextView)view.findViewById(R.id.attachment_info);
- ImageView attachmentIcon = (ImageView)view.findViewById(R.id.attachment_icon);
- Button attachmentView = (Button)view.findViewById(R.id.view);
- Button attachmentDownload = (Button)view.findViewById(R.id.download);
-
- if ((!MimeUtility.mimeTypeMatches(attachment.contentType,
- Email.ACCEPTABLE_ATTACHMENT_VIEW_TYPES))
- || (MimeUtility.mimeTypeMatches(attachment.contentType,
- Email.UNACCEPTABLE_ATTACHMENT_VIEW_TYPES))) {
- attachmentView.setVisibility(View.GONE);
- }
- if ((!MimeUtility.mimeTypeMatches(attachment.contentType,
- Email.ACCEPTABLE_ATTACHMENT_DOWNLOAD_TYPES))
- || (MimeUtility.mimeTypeMatches(attachment.contentType,
- Email.UNACCEPTABLE_ATTACHMENT_DOWNLOAD_TYPES))) {
- attachmentDownload.setVisibility(View.GONE);
- }
-
- if (attachment.size > Email.MAX_ATTACHMENT_DOWNLOAD_SIZE) {
- attachmentView.setVisibility(View.GONE);
- attachmentDownload.setVisibility(View.GONE);
- }
-
- attachment.viewButton = attachmentView;
- attachment.downloadButton = attachmentDownload;
- attachment.iconView = attachmentIcon;
-
- view.setTag(attachment);
- attachmentView.setOnClickListener(this);
- attachmentView.setTag(attachment);
- attachmentDownload.setOnClickListener(this);
- attachmentDownload.setTag(attachment);
-
- attachmentName.setText(name);
- attachmentInfo.setText(formatSize(size));
-
- Bitmap previewIcon = getPreviewIcon(attachment);
- if (previewIcon != null) {
- attachmentIcon.setImageBitmap(previewIcon);
- }
-
- mHandler.addAttachment(view);
- }
-
- if (part.getBody() instanceof Multipart) {
- Multipart mp = (Multipart)part.getBody();
- for (int i = 0; i < mp.getCount(); i++) {
- renderAttachments(mp.getBodyPart(i), depth + 1);
- }
- }
- }
-
- class Listener extends MessagingListener {
- @Override
- public void loadMessageForViewHeadersAvailable(Account account, String folder, String uid,
- final Message message) {
- MessageView.this.mMessage = message;
- try {
- String subjectText = message.getSubject();
- String fromText = Address.toFriendly(message.getFrom());
- Date sentDate = message.getSentDate();
- String timeText = mTimeFormat.format(sentDate);
- String dateText = Utility.isDateToday(sentDate) ? null :
- mDateFormat.format(sentDate);
- String toText = Address.toFriendly(message.getRecipients(RecipientType.TO));
- String ccText = Address.toFriendly(message.getRecipients(RecipientType.CC));
- boolean hasAttachments = ((LocalMessage) message).getAttachmentCount() > 0;
- mHandler.setHeaders(subjectText,
- fromText,
- timeText,
- dateText,
- toText,
- ccText,
- hasAttachments);
- }
- catch (MessagingException me) {
- if (Config.LOGV) {
- Log.v(Email.LOG_TAG, "loadMessageForViewHeadersAvailable", me);
- }
- }
- }
-
- @Override
- public void loadMessageForViewBodyAvailable(Account account, String folder, String uid,
- Message message) {
- MessageView.this.mMessage = message;
- try {
- Part part = MimeUtility.findFirstPartByMimeType(mMessage, "text/html");
- if (part == null) {
- part = MimeUtility.findFirstPartByMimeType(mMessage, "text/plain");
- }
- if (part != null) {
- String text = MimeUtility.getTextFromPart(part);
- if (part.getMimeType().equalsIgnoreCase("text/html")) {
- text = text.replaceAll("cid:", "http://cid/");
- } else {
- /*
- * Linkify the plain text and convert it to HTML by replacing
- * \r?\n with <br> and adding a html/body wrapper.
- */
- Matcher m = Regex.WEB_URL_PATTERN.matcher(text);
- StringBuffer sb = new StringBuffer();
- while (m.find()) {
- int start = m.start();
- if (start != 0 && text.charAt(start - 1) != '@') {
- m.appendReplacement(sb, "<a href=\"$0\">$0</a>");
- }
- else {
- m.appendReplacement(sb, "$0");
- }
- }
- m.appendTail(sb);
- text = sb.toString().replaceAll("\r?\n", "<br>");
- text = "<html><body>" + text + "</body></html>";
- }
-
- /*
- * TODO this should be smarter, change to regex for img, but consider how to
- * get backgroung images and a million other things that HTML allows.
- */
- if (text.contains("img")) {
- mHandler.showShowPictures(true);
- }
-
- mMessageContentView.loadDataWithBaseURL("email://", text, "text/html",
- "utf-8", null);
- }
- else {
- mMessageContentView.loadUrl("file:///android_asset/empty.html");
- }
- renderAttachments(mMessage, 0);
- }
- catch (Exception e) {
- if (Config.LOGV) {
- Log.v(Email.LOG_TAG, "loadMessageForViewBodyAvailable", e);
- }
- }
- }
-
- @Override
- public void loadMessageForViewFailed(Account account, String folder, String uid,
- final String message) {
- mHandler.post(new Runnable() {
- public void run() {
- setProgressBarIndeterminateVisibility(false);
- mHandler.networkError();
- mMessageContentView.loadUrl("file:///android_asset/empty.html");
- }
- });
- }
-
- @Override
- public void loadMessageForViewFinished(Account account, String folder, String uid,
- Message message) {
- mHandler.post(new Runnable() {
- public void run() {
- setProgressBarIndeterminateVisibility(false);
- }
- });
- }
-
- @Override
- public void loadMessageForViewStarted(Account account, String folder, String uid) {
- mHandler.post(new Runnable() {
- public void run() {
- mMessageContentView.loadUrl("file:///android_asset/loading.html");
- setProgressBarIndeterminateVisibility(true);
- }
- });
- }
-
- @Override
- public void loadAttachmentStarted(Account account, Message message,
- Part part, Object tag, boolean requiresDownload) {
- mHandler.setAttachmentsEnabled(false);
- mHandler.progress(true);
- if (requiresDownload) {
- mHandler.fetchingAttachment();
- }
- }
-
- @Override
- public void loadAttachmentFinished(Account account, Message message,
- Part part, Object tag) {
- mHandler.setAttachmentsEnabled(true);
- mHandler.progress(false);
-
- Object[] params = (Object[]) tag;
- boolean download = (Boolean) params[0];
- Attachment attachment = (Attachment) params[1];
-
- if (download) {
- try {
- File file = createUniqueFile(Environment.getExternalStorageDirectory(),
- attachment.name);
- Uri uri = AttachmentProvider.getAttachmentUri(
- mAccount,
- attachment.part.getAttachmentId());
- InputStream in = getContentResolver().openInputStream(uri);
- OutputStream out = new FileOutputStream(file);
- IOUtils.copy(in, out);
- out.flush();
- out.close();
- in.close();
- mHandler.attachmentSaved(file.getName());
- new MediaScannerNotifier(MessageView.this, file);
- }
- catch (IOException ioe) {
- mHandler.attachmentNotSaved();
- }
- }
- else {
- Uri uri = AttachmentProvider.getAttachmentUri(
- mAccount,
- attachment.part.getAttachmentId());
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(uri);
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- startActivity(intent);
- }
- }
-
- @Override
- public void loadAttachmentFailed(Account account, Message message, Part part,
- Object tag, String reason) {
- mHandler.setAttachmentsEnabled(true);
- mHandler.progress(false);
- mHandler.networkError();
- }
- }
-
- /**
- * This notifier is created after an attachment completes downloaded. It attaches to the
- * media scanner and waits to handle the completion of the scan. At that point it tries
- * to start an ACTION_VIEW activity for the attachment.
- */
- private static class MediaScannerNotifier implements MediaScannerConnectionClient {
- private Context mContext;
- private MediaScannerConnection mConnection;
- private File mFile;
-
- public MediaScannerNotifier(Context context, File file) {
- mContext = context;
- mFile = file;
- mConnection = new MediaScannerConnection(context, this);
- mConnection.connect();
- }
-
- public void onMediaScannerConnected() {
- mConnection.scanFile(mFile.getAbsolutePath(), null);
- }
-
- public void onScanCompleted(String path, Uri uri) {
- try {
- if (uri != null) {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(uri);
- mContext.startActivity(intent);
- }
- } finally {
- mConnection.disconnect();
- mContext = null;
- }
- }
- }
-}
diff --git a/src/com/android/email/activity/ProgressListener.java b/src/com/android/email/activity/ProgressListener.java
deleted file mode 100644
index 641e62467..000000000
--- a/src/com/android/email/activity/ProgressListener.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity;
-
-import android.content.Context;
-
-/**
- * A listener that the user can register for global, persistent progress events.
- */
-public interface ProgressListener {
- /**
- * @param context
- * @param title
- * @param message
- * @param currentProgress
- * @param maxProgress
- * @param indeterminate
- */
- void showProgress(Context context, String title, String message, long currentProgress,
- long maxProgress, boolean indeterminate);
-
- /**
- * @param context
- * @param title
- * @param message
- * @param currentProgress
- * @param maxProgress
- * @param indeterminate
- */
- void updateProgress(Context context, String title, String message, long currentProgress,
- long maxProgress, boolean indeterminate);
-
- /**
- * @param context
- */
- void hideProgress(Context context);
-}
diff --git a/src/com/android/email/activity/Welcome.java b/src/com/android/email/activity/Welcome.java
deleted file mode 100644
index f912bf5c8..000000000
--- a/src/com/android/email/activity/Welcome.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity;
-
-import com.android.email.Account;
-import com.android.email.Email;
-import com.android.email.Preferences;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-
-/**
- * The Welcome activity initializes the application and decides what Activity
- * the user should start with.
- * If no accounts are configured the user is taken to the Accounts Activity where they
- * can configure an account.
- * If a single account is configured the user is taken directly to the FolderMessageList for
- * the INBOX of that account.
- * If more than one account is configuref the user is takaen to the Accounts Activity so they
- * can select an account.
- */
-public class Welcome extends Activity {
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- Account[] accounts = Preferences.getPreferences(this).getAccounts();
- if (accounts.length == 1) {
- FolderMessageList.actionHandleAccount(this, accounts[0], Email.INBOX);
- } else {
- Accounts.actionShowAccounts(this);
- }
-
- finish();
- }
-}
diff --git a/src/com/android/email/activity/setup/AccountSettings.java b/src/com/android/email/activity/setup/AccountSettings.java
deleted file mode 100644
index a26d03658..000000000
--- a/src/com/android/email/activity/setup/AccountSettings.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity.setup;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.view.KeyEvent;
-import android.preference.PreferenceActivity;
-import android.preference.EditTextPreference;
-import android.preference.ListPreference;
-import android.preference.CheckBoxPreference;
-import android.preference.Preference;
-import android.preference.RingtonePreference;
-
-import com.android.email.Account;
-import com.android.email.Email;
-import com.android.email.Preferences;
-import com.android.email.R;
-
-public class AccountSettings extends PreferenceActivity {
- private static final String EXTRA_ACCOUNT = "account";
-
- private static final String PREFERENCE_TOP_CATERGORY = "account_settings";
- private static final String PREFERENCE_DESCRIPTION = "account_description";
- private static final String PREFERENCE_NAME = "account_name";
- private static final String PREFERENCE_FREQUENCY = "account_check_frequency";
- private static final String PREFERENCE_DEFAULT = "account_default";
- private static final String PREFERENCE_NOTIFY = "account_notify";
- private static final String PREFERENCE_VIBRATE = "account_vibrate";
- private static final String PREFERENCE_RINGTONE = "account_ringtone";
- private static final String PREFERENCE_INCOMING = "incoming";
- private static final String PREFERENCE_OUTGOING = "outgoing";
- private static final String PREFERENCE_ADD_ACCOUNT = "add_account";
-
- private Account mAccount;
-
- private EditTextPreference mAccountDescription;
- private EditTextPreference mAccountName;
- private ListPreference mCheckFrequency;
- private CheckBoxPreference mAccountDefault;
- private CheckBoxPreference mAccountNotify;
- private CheckBoxPreference mAccountVibrate;
- private RingtonePreference mAccountRingtone;
-
- public static void actionSettings(Context context, Account account) {
- Intent i = new Intent(context, AccountSettings.class);
- i.putExtra(EXTRA_ACCOUNT, account);
- context.startActivity(i);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mAccount = (Account)getIntent().getSerializableExtra(EXTRA_ACCOUNT);
-
- addPreferencesFromResource(R.xml.account_settings_preferences);
-
- Preference category = findPreference(PREFERENCE_TOP_CATERGORY);
- category.setTitle(getString(R.string.account_settings_title_fmt));
-
- mAccountDescription = (EditTextPreference) findPreference(PREFERENCE_DESCRIPTION);
- mAccountDescription.setSummary(mAccount.getDescription());
- mAccountDescription.setText(mAccount.getDescription());
- mAccountDescription.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- final String summary = newValue.toString();
- mAccountDescription.setSummary(summary);
- mAccountDescription.setText(summary);
- return false;
- }
- });
-
- mAccountName = (EditTextPreference) findPreference(PREFERENCE_NAME);
- mAccountName.setSummary(mAccount.getName());
- mAccountName.setText(mAccount.getName());
- mAccountName.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- final String summary = newValue.toString();
- mAccountName.setSummary(summary);
- mAccountName.setText(summary);
- return false;
- }
- });
-
- mCheckFrequency = (ListPreference) findPreference(PREFERENCE_FREQUENCY);
- mCheckFrequency.setValue(String.valueOf(mAccount.getAutomaticCheckIntervalMinutes()));
- mCheckFrequency.setSummary(mCheckFrequency.getEntry());
- mCheckFrequency.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- final String summary = newValue.toString();
- int index = mCheckFrequency.findIndexOfValue(summary);
- mCheckFrequency.setSummary(mCheckFrequency.getEntries()[index]);
- mCheckFrequency.setValue(summary);
- return false;
- }
- });
-
- mAccountDefault = (CheckBoxPreference) findPreference(PREFERENCE_DEFAULT);
- mAccountDefault.setChecked(
- mAccount.equals(Preferences.getPreferences(this).getDefaultAccount()));
-
- mAccountNotify = (CheckBoxPreference) findPreference(PREFERENCE_NOTIFY);
- mAccountNotify.setChecked(mAccount.isNotifyNewMail());
-
- mAccountRingtone = (RingtonePreference) findPreference(PREFERENCE_RINGTONE);
-
- // XXX: The following two lines act as a workaround for the RingtonePreference
- // which does not let us set/get the value programmatically
- SharedPreferences prefs = mAccountRingtone.getPreferenceManager().getSharedPreferences();
- prefs.edit().putString(PREFERENCE_RINGTONE, mAccount.getRingtone()).commit();
-
- mAccountVibrate = (CheckBoxPreference) findPreference(PREFERENCE_VIBRATE);
- mAccountVibrate.setChecked(mAccount.isVibrate());
-
- findPreference(PREFERENCE_INCOMING).setOnPreferenceClickListener(
- new Preference.OnPreferenceClickListener() {
- public boolean onPreferenceClick(Preference preference) {
- onIncomingSettings();
- return true;
- }
- });
-
- findPreference(PREFERENCE_OUTGOING).setOnPreferenceClickListener(
- new Preference.OnPreferenceClickListener() {
- public boolean onPreferenceClick(Preference preference) {
- onOutgoingSettings();
- return true;
- }
- });
- findPreference(PREFERENCE_ADD_ACCOUNT).setOnPreferenceClickListener(
- new Preference.OnPreferenceClickListener() {
- public boolean onPreferenceClick(Preference preference) {
- onAddNewAccount();
- return true;
- }
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mAccount.refresh(Preferences.getPreferences(this));
- }
-
- private void saveSettings() {
- if (mAccountDefault.isChecked()) {
- Preferences.getPreferences(this).setDefaultAccount(mAccount);
- }
- mAccount.setDescription(mAccountDescription.getText());
- mAccount.setName(mAccountName.getText());
- mAccount.setNotifyNewMail(mAccountNotify.isChecked());
- mAccount.setAutomaticCheckIntervalMinutes(Integer.parseInt(mCheckFrequency.getValue()));
- mAccount.setVibrate(mAccountVibrate.isChecked());
- SharedPreferences prefs = mAccountRingtone.getPreferenceManager().getSharedPreferences();
- mAccount.setRingtone(prefs.getString(PREFERENCE_RINGTONE, null));
- mAccount.save(Preferences.getPreferences(this));
- Email.setServicesEnabled(this);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- saveSettings();
- }
- return super.onKeyDown(keyCode, event);
- }
-
- private void onIncomingSettings() {
- AccountSetupIncoming.actionEditIncomingSettings(this, mAccount);
- }
-
- private void onOutgoingSettings() {
- AccountSetupOutgoing.actionEditOutgoingSettings(this, mAccount);
- }
-
- private void onAddNewAccount() {
- AccountSetupBasics.actionNewAccount(this);
- finish();
- }
-}
diff --git a/src/com/android/email/activity/setup/AccountSetupAccountType.java b/src/com/android/email/activity/setup/AccountSetupAccountType.java
deleted file mode 100644
index cf5341a72..000000000
--- a/src/com/android/email/activity/setup/AccountSetupAccountType.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity.setup;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-
-import com.android.email.Account;
-import com.android.email.R;
-
-/**
- * Prompts the user to select an account type. The account type, along with the
- * passed in email address, password and makeDefault are then passed on to the
- * AccountSetupIncoming activity.
- */
-public class AccountSetupAccountType extends Activity implements OnClickListener {
- private static final String EXTRA_ACCOUNT = "account";
-
- private static final String EXTRA_MAKE_DEFAULT = "makeDefault";
-
- private Account mAccount;
-
- private boolean mMakeDefault;
-
- public static void actionSelectAccountType(Context context, Account account, boolean makeDefault) {
- Intent i = new Intent(context, AccountSetupAccountType.class);
- i.putExtra(EXTRA_ACCOUNT, account);
- i.putExtra(EXTRA_MAKE_DEFAULT, makeDefault);
- context.startActivity(i);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.account_setup_account_type);
- ((Button)findViewById(R.id.pop)).setOnClickListener(this);
- ((Button)findViewById(R.id.imap)).setOnClickListener(this);
-
- mAccount = (Account)getIntent().getSerializableExtra(EXTRA_ACCOUNT);
- mMakeDefault = (boolean)getIntent().getBooleanExtra(EXTRA_MAKE_DEFAULT, false);
- }
-
- private void onPop() {
- try {
- URI uri = new URI(mAccount.getStoreUri());
- uri = new URI("pop3", uri.getUserInfo(), uri.getHost(), uri.getPort(), null, null, null);
- mAccount.setStoreUri(uri.toString());
- } catch (URISyntaxException use) {
- /*
- * This should not happen.
- */
- throw new Error(use);
- }
- AccountSetupIncoming.actionIncomingSettings(this, mAccount, mMakeDefault);
- finish();
- }
-
- /**
- * The user has selected an IMAP account type. Try to put together a URI using the entered
- * email address. Also set the mail delete policy here, because there is no UI (for IMAP).
- */
- private void onImap() {
- try {
- URI uri = new URI(mAccount.getStoreUri());
- uri = new URI("imap", uri.getUserInfo(), uri.getHost(), uri.getPort(), null, null, null);
- mAccount.setStoreUri(uri.toString());
- } catch (URISyntaxException use) {
- /*
- * This should not happen.
- */
- throw new Error(use);
- }
- // Delete policy must be set explicitly, because IMAP does not provide a UI selection
- // for it. This logic needs to be followed in the auto setup flow as well.
- mAccount.setDeletePolicy(Account.DELETE_POLICY_ON_DELETE);
- AccountSetupIncoming.actionIncomingSettings(this, mAccount, mMakeDefault);
- finish();
- }
-
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.pop:
- onPop();
- break;
- case R.id.imap:
- onImap();
- break;
- }
- }
-}
diff --git a/src/com/android/email/activity/setup/AccountSetupBasics.java b/src/com/android/email/activity/setup/AccountSetupBasics.java
deleted file mode 100644
index fcd9ce7cc..000000000
--- a/src/com/android/email/activity/setup/AccountSetupBasics.java
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity.setup;
-
-import java.io.Serializable;
-import java.net.URI;
-import java.net.URISyntaxException;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.res.XmlResourceParser;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.Contacts;
-import android.provider.Contacts.People.ContactMethods;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.EditText;
-import android.widget.Toast;
-
-import com.android.email.Account;
-import com.android.email.Email;
-import com.android.email.EmailAddressValidator;
-import com.android.email.Preferences;
-import com.android.email.R;
-import com.android.email.Utility;
-import com.android.email.activity.Debug;
-
-/**
- * Prompts the user for the email address and password. Also prompts for
- * "Use this account as default" if this is the 2nd+ account being set up.
- * Attempts to lookup default settings for the domain the user specified. If the
- * domain is known the settings are handed off to the AccountSetupCheckSettings
- * activity. If no settings are found the settings are handed off to the
- * AccountSetupAccountType activity.
- */
-public class AccountSetupBasics extends Activity
- implements OnClickListener, TextWatcher {
- private final static boolean ENTER_DEBUG_SCREEN = true;
- private final static String EXTRA_ACCOUNT = "com.android.email.AccountSetupBasics.account";
- private final static int DIALOG_NOTE = 1;
- private final static String STATE_KEY_PROVIDER =
- "com.android.email.AccountSetupBasics.provider";
-
- // NOTE: If you change this value, confirm that the new interval exists in arrays.xml
- private final static int DEFAULT_ACCOUNT_CHECK_INTERVAL = 15;
-
- private Preferences mPrefs;
- private EditText mEmailView;
- private EditText mPasswordView;
- private CheckBox mDefaultView;
- private Button mNextButton;
- private Button mManualSetupButton;
- private Account mAccount;
- private Provider mProvider;
-
- private EmailAddressValidator mEmailValidator = new EmailAddressValidator();
-
- public static void actionNewAccount(Context context) {
- Intent i = new Intent(context, AccountSetupBasics.class);
- context.startActivity(i);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.account_setup_basics);
- mPrefs = Preferences.getPreferences(this);
- mEmailView = (EditText)findViewById(R.id.account_email);
- mPasswordView = (EditText)findViewById(R.id.account_password);
- mDefaultView = (CheckBox)findViewById(R.id.account_default);
- mNextButton = (Button)findViewById(R.id.next);
- mManualSetupButton = (Button)findViewById(R.id.manual_setup);
-
- mNextButton.setOnClickListener(this);
- mManualSetupButton.setOnClickListener(this);
-
- mEmailView.addTextChangedListener(this);
- mPasswordView.addTextChangedListener(this);
-
- if (mPrefs.getAccounts().length > 0) {
- mDefaultView.setVisibility(View.VISIBLE);
- }
-
- if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_ACCOUNT)) {
- mAccount = (Account)savedInstanceState.getSerializable(EXTRA_ACCOUNT);
- }
-
- if (savedInstanceState != null && savedInstanceState.containsKey(STATE_KEY_PROVIDER)) {
- mProvider = (Provider)savedInstanceState.getSerializable(STATE_KEY_PROVIDER);
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
- validateFields();
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putSerializable(EXTRA_ACCOUNT, mAccount);
- if (mProvider != null) {
- outState.putSerializable(STATE_KEY_PROVIDER, mProvider);
- }
- }
-
- public void afterTextChanged(Editable s) {
- validateFields();
- }
-
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
-
- private void validateFields() {
- boolean valid = Utility.requiredFieldValid(mEmailView)
- && Utility.requiredFieldValid(mPasswordView)
- && mEmailValidator.isValid(mEmailView.getText().toString().trim());
- mNextButton.setEnabled(valid);
- mManualSetupButton.setEnabled(valid);
- /*
- * Dim the next button's icon to 50% if the button is disabled.
- * TODO this can probably be done with a stateful drawable. Check into it.
- * android:state_enabled
- */
- Utility.setCompoundDrawablesAlpha(mNextButton, mNextButton.isEnabled() ? 255 : 128);
- }
-
- private String getOwnerName() {
- String name = null;
- String projection[] = {
- ContactMethods.NAME
- };
- Cursor c = getContentResolver().query(
- Uri.withAppendedPath(Contacts.People.CONTENT_URI, "owner"), projection, null, null,
- null);
- if (c.getCount() > 0) {
- c.moveToFirst();
- name = c.getString(0);
- c.close();
- }
-
- if (name == null || name.length() == 0) {
- Account account = Preferences.getPreferences(this).getDefaultAccount();
- if (account != null) {
- name = account.getName();
- }
- }
- return name;
- }
-
- @Override
- public Dialog onCreateDialog(int id) {
- if (id == DIALOG_NOTE) {
- if (mProvider != null && mProvider.note != null) {
- return new AlertDialog.Builder(this)
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setTitle(android.R.string.dialog_alert_title)
- .setMessage(mProvider.note)
- .setPositiveButton(
- getString(R.string.okay_action),
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- finishAutoSetup();
- }
- })
- .setNegativeButton(
- getString(R.string.cancel_action),
- null)
- .create();
- }
- }
- return null;
- }
-
- private void finishAutoSetup() {
- String email = mEmailView.getText().toString().trim();
- String password = mPasswordView.getText().toString().trim();
- String[] emailParts = email.split("@");
- String user = emailParts[0];
- String domain = emailParts[1];
- URI incomingUri = null;
- URI outgoingUri = null;
- try {
- String incomingUsername = mProvider.incomingUsernameTemplate;
- incomingUsername = incomingUsername.replaceAll("\\$email", email);
- incomingUsername = incomingUsername.replaceAll("\\$user", user);
- incomingUsername = incomingUsername.replaceAll("\\$domain", domain);
-
- URI incomingUriTemplate = mProvider.incomingUriTemplate;
- incomingUri = new URI(incomingUriTemplate.getScheme(), incomingUsername + ":"
- + password, incomingUriTemplate.getHost(), incomingUriTemplate.getPort(), null,
- null, null);
-
- String outgoingUsername = mProvider.outgoingUsernameTemplate;
- outgoingUsername = outgoingUsername.replaceAll("\\$email", email);
- outgoingUsername = outgoingUsername.replaceAll("\\$user", user);
- outgoingUsername = outgoingUsername.replaceAll("\\$domain", domain);
-
- URI outgoingUriTemplate = mProvider.outgoingUriTemplate;
- outgoingUri = new URI(outgoingUriTemplate.getScheme(), outgoingUsername + ":"
- + password, outgoingUriTemplate.getHost(), outgoingUriTemplate.getPort(), null,
- null, null);
- } catch (URISyntaxException use) {
- /*
- * If there is some problem with the URI we give up and go on to
- * manual setup.
- */
- onManualSetup();
- return;
- }
-
- mAccount = new Account(this);
- mAccount.setName(getOwnerName());
- mAccount.setEmail(email);
- mAccount.setStoreUri(incomingUri.toString());
- mAccount.setSenderUri(outgoingUri.toString());
- mAccount.setDraftsFolderName(getString(R.string.special_mailbox_name_drafts));
- mAccount.setTrashFolderName(getString(R.string.special_mailbox_name_trash));
- mAccount.setOutboxFolderName(getString(R.string.special_mailbox_name_outbox));
- mAccount.setSentFolderName(getString(R.string.special_mailbox_name_sent));
- if (incomingUri.toString().startsWith("imap")) {
- // Delete policy must be set explicitly, because IMAP does not provide a UI selection
- // for it. This logic needs to be followed in the auto setup flow as well.
- mAccount.setDeletePolicy(Account.DELETE_POLICY_ON_DELETE);
- }
- mAccount.setAutomaticCheckIntervalMinutes(DEFAULT_ACCOUNT_CHECK_INTERVAL);
- AccountSetupCheckSettings.actionCheckSettings(this, mAccount, true, true);
- }
-
- private void onNext() {
- String email = mEmailView.getText().toString().trim();
- String[] emailParts = email.split("@");
- String domain = emailParts[1].trim();
- mProvider = findProviderForDomain(domain);
- if (mProvider == null) {
- /*
- * We don't have default settings for this account, start the manual
- * setup process.
- */
- onManualSetup();
- return;
- }
-
- if (mProvider.note != null) {
- showDialog(DIALOG_NOTE);
- }
- else {
- finishAutoSetup();
- }
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (resultCode == RESULT_OK) {
- mAccount.setDescription(mAccount.getEmail());
- mAccount.save(Preferences.getPreferences(this));
- if (mDefaultView.isChecked()) {
- Preferences.getPreferences(this).setDefaultAccount(mAccount);
- }
- Email.setServicesEnabled(this);
- AccountSetupNames.actionSetNames(this, mAccount);
- finish();
- }
- }
-
- private void onManualSetup() {
- String email = mEmailView.getText().toString().trim();
- String password = mPasswordView.getText().toString().trim();
- String[] emailParts = email.split("@");
- String user = emailParts[0].trim();
- String domain = emailParts[1].trim();
-
- // Alternate entry to the debug options screen (for devices without a physical keyboard:
- // Username: d@d
- // Password: debug
- if (ENTER_DEBUG_SCREEN && "d@d".equals(email) && "debug".equals(password)) {
- startActivity(new Intent(this, Debug.class));
- return;
- }
-
- mAccount = new Account(this);
- mAccount.setName(getOwnerName());
- mAccount.setEmail(email);
- try {
- URI uri = new URI("placeholder", user + ":" + password, domain, -1, null, null, null);
- mAccount.setStoreUri(uri.toString());
- mAccount.setSenderUri(uri.toString());
- } catch (URISyntaxException use) {
- // If we can't set up the URL, don't continue - account setup pages will fail too
- Toast.makeText(this, R.string.account_setup_username_password_toast, Toast.LENGTH_LONG)
- .show();
- mAccount = null;
- return;
- }
- mAccount.setDraftsFolderName(getString(R.string.special_mailbox_name_drafts));
- mAccount.setTrashFolderName(getString(R.string.special_mailbox_name_trash));
- mAccount.setOutboxFolderName(getString(R.string.special_mailbox_name_outbox));
- mAccount.setSentFolderName(getString(R.string.special_mailbox_name_sent));
-
- mAccount.setAutomaticCheckIntervalMinutes(DEFAULT_ACCOUNT_CHECK_INTERVAL);
-
- AccountSetupAccountType.actionSelectAccountType(this, mAccount, mDefaultView.isChecked());
- finish();
- }
-
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.next:
- onNext();
- break;
- case R.id.manual_setup:
- onManualSetup();
- break;
- }
- }
-
- /**
- * Attempts to get the given attribute as a String resource first, and if it fails
- * returns the attribute as a simple String value.
- * @param xml
- * @param name
- * @return
- */
- private String getXmlAttribute(XmlResourceParser xml, String name) {
- int resId = xml.getAttributeResourceValue(null, name, 0);
- if (resId == 0) {
- return xml.getAttributeValue(null, name);
- }
- else {
- return getString(resId);
- }
- }
-
- /**
- * Search the list of known Email providers looking for one that matches the user's email
- * domain. We look in providers_product.xml first, followed by the entries in
- * platform providers.xml. This provides a nominal override capability.
- *
- * A match is defined as any provider entry for which the "domain" attribute matches.
- *
- * @param domain The domain portion of the user's email address
- * @return suitable Provider definition, or null if no match found
- */
- private Provider findProviderForDomain(String domain) {
- Provider p = findProviderForDomain(domain, R.xml.providers_product);
- if (p == null) {
- p = findProviderForDomain(domain, R.xml.providers);
- }
- return p;
- }
-
- /**
- * Search a single resource containing known Email provider definitions.
- *
- * @param domain The domain portion of the user's email address
- * @param resourceId Id of the provider resource to scan
- * @return suitable Provider definition, or null if no match found
- */
- private Provider findProviderForDomain(String domain, int resourceId) {
- try {
- XmlResourceParser xml = getResources().getXml(resourceId);
- int xmlEventType;
- Provider provider = null;
- while ((xmlEventType = xml.next()) != XmlResourceParser.END_DOCUMENT) {
- if (xmlEventType == XmlResourceParser.START_TAG
- && "provider".equals(xml.getName())
- && domain.equalsIgnoreCase(getXmlAttribute(xml, "domain"))) {
- provider = new Provider();
- provider.id = getXmlAttribute(xml, "id");
- provider.label = getXmlAttribute(xml, "label");
- provider.domain = getXmlAttribute(xml, "domain");
- provider.note = getXmlAttribute(xml, "note");
- }
- else if (xmlEventType == XmlResourceParser.START_TAG
- && "incoming".equals(xml.getName())
- && provider != null) {
- provider.incomingUriTemplate = new URI(getXmlAttribute(xml, "uri"));
- provider.incomingUsernameTemplate = getXmlAttribute(xml, "username");
- }
- else if (xmlEventType == XmlResourceParser.START_TAG
- && "outgoing".equals(xml.getName())
- && provider != null) {
- provider.outgoingUriTemplate = new URI(getXmlAttribute(xml, "uri"));
- provider.outgoingUsernameTemplate = getXmlAttribute(xml, "username");
- }
- else if (xmlEventType == XmlResourceParser.END_TAG
- && "provider".equals(xml.getName())
- && provider != null) {
- return provider;
- }
- }
- }
- catch (Exception e) {
- Log.e(Email.LOG_TAG, "Error while trying to load provider settings.", e);
- }
- return null;
- }
-
- static class Provider implements Serializable {
- private static final long serialVersionUID = 8511656164616538989L;
-
- public String id;
-
- public String label;
-
- public String domain;
-
- public URI incomingUriTemplate;
-
- public String incomingUsernameTemplate;
-
- public URI outgoingUriTemplate;
-
- public String outgoingUsernameTemplate;
-
- public String note;
- }
-}
diff --git a/src/com/android/email/activity/setup/AccountSetupCheckSettings.java b/src/com/android/email/activity/setup/AccountSetupCheckSettings.java
deleted file mode 100644
index c54203fd8..000000000
--- a/src/com/android/email/activity/setup/AccountSetupCheckSettings.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity.setup;
-
-import com.android.email.Account;
-import com.android.email.R;
-import com.android.email.mail.AuthenticationFailedException;
-import com.android.email.mail.CertificateValidationException;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Store;
-import com.android.email.mail.Sender;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Process;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-/**
- * Checks the given settings to make sure that they can be used to send and
- * receive mail.
- *
- * XXX NOTE: The manifest for this app has it ignore config changes, because
- * it doesn't correctly deal with restarting while its thread is running.
- */
-public class AccountSetupCheckSettings extends Activity implements OnClickListener {
- private static final String EXTRA_ACCOUNT = "account";
-
- private static final String EXTRA_CHECK_INCOMING = "checkIncoming";
-
- private static final String EXTRA_CHECK_OUTGOING = "checkOutgoing";
-
- private Handler mHandler = new Handler();
-
- private ProgressBar mProgressBar;
-
- private TextView mMessageView;
-
- private Account mAccount;
-
- private boolean mCheckIncoming;
-
- private boolean mCheckOutgoing;
-
- private boolean mCanceled;
-
- private boolean mDestroyed;
-
- public static void actionCheckSettings(Activity context, Account account,
- boolean checkIncoming, boolean checkOutgoing) {
- Intent i = new Intent(context, AccountSetupCheckSettings.class);
- i.putExtra(EXTRA_ACCOUNT, account);
- i.putExtra(EXTRA_CHECK_INCOMING, checkIncoming);
- i.putExtra(EXTRA_CHECK_OUTGOING, checkOutgoing);
- context.startActivityForResult(i, 1);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.account_setup_check_settings);
- mMessageView = (TextView)findViewById(R.id.message);
- mProgressBar = (ProgressBar)findViewById(R.id.progress);
- ((Button)findViewById(R.id.cancel)).setOnClickListener(this);
-
- setMessage(R.string.account_setup_check_settings_retr_info_msg);
- mProgressBar.setIndeterminate(true);
-
- mAccount = (Account)getIntent().getSerializableExtra(EXTRA_ACCOUNT);
- mCheckIncoming = (boolean)getIntent().getBooleanExtra(EXTRA_CHECK_INCOMING, false);
- mCheckOutgoing = (boolean)getIntent().getBooleanExtra(EXTRA_CHECK_OUTGOING, false);
-
- new Thread() {
- public void run() {
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- try {
- if (mDestroyed) {
- return;
- }
- if (mCanceled) {
- finish();
- return;
- }
- if (mCheckIncoming) {
- setMessage(R.string.account_setup_check_settings_check_incoming_msg);
- Store store = Store.getInstance(mAccount.getStoreUri(), getApplication());
- store.checkSettings();
- }
- if (mDestroyed) {
- return;
- }
- if (mCanceled) {
- finish();
- return;
- }
- if (mCheckOutgoing) {
- setMessage(R.string.account_setup_check_settings_check_outgoing_msg);
- Sender sender = Sender.getInstance(mAccount.getSenderUri());
- sender.close();
- sender.open();
- sender.close();
- }
- if (mDestroyed) {
- return;
- }
- if (mCanceled) {
- finish();
- return;
- }
- setResult(RESULT_OK);
- finish();
- } catch (final AuthenticationFailedException afe) {
- String message = afe.getMessage();
- int id = (message == null)
- ? R.string.account_setup_failed_dlg_auth_message
- : R.string.account_setup_failed_dlg_auth_message_fmt;
- showErrorDialog(id, message);
- } catch (final CertificateValidationException cve) {
- String message = cve.getMessage();
- int id = (message == null)
- ? R.string.account_setup_failed_dlg_certificate_message
- : R.string.account_setup_failed_dlg_certificate_message_fmt;
- showErrorDialog(id, message);
- } catch (final MessagingException me) {
- int id;
- String message = me.getMessage();
- switch (me.getExceptionType()) {
- case MessagingException.IOERROR:
- id = R.string.account_setup_failed_ioerror;
- break;
- case MessagingException.TLS_REQUIRED:
- id = R.string.account_setup_failed_tls_required;
- break;
- case MessagingException.AUTH_REQUIRED:
- id = R.string.account_setup_failed_auth_required;
- break;
- case MessagingException.GENERAL_SECURITY:
- id = R.string.account_setup_failed_security;
- break;
- default:
- id = (message == null)
- ? R.string.account_setup_failed_dlg_server_message
- : R.string.account_setup_failed_dlg_server_message_fmt;
- break;
- }
- showErrorDialog(id, message);
- }
- }
- }.start();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- mDestroyed = true;
- mCanceled = true;
- }
-
- private void setMessage(final int resId) {
- mHandler.post(new Runnable() {
- public void run() {
- if (mDestroyed) {
- return;
- }
- mMessageView.setText(getString(resId));
- }
- });
- }
-
- private void showErrorDialog(final int msgResId, final Object... args) {
- mHandler.post(new Runnable() {
- public void run() {
- if (mDestroyed) {
- return;
- }
- mProgressBar.setIndeterminate(false);
- new AlertDialog.Builder(AccountSetupCheckSettings.this)
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setTitle(getString(R.string.account_setup_failed_dlg_title))
- .setMessage(getString(msgResId, args))
- .setCancelable(true)
- .setPositiveButton(
- getString(R.string.account_setup_failed_dlg_edit_details_action),
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- finish();
- }
- })
- .show();
- }
- });
- }
-
- private void onCancel() {
- mCanceled = true;
- setMessage(R.string.account_setup_check_settings_canceling_msg);
- }
-
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.cancel:
- onCancel();
- break;
- }
- }
-}
diff --git a/src/com/android/email/activity/setup/AccountSetupIncoming.java b/src/com/android/email/activity/setup/AccountSetupIncoming.java
deleted file mode 100644
index 95ddf11c4..000000000
--- a/src/com/android/email/activity/setup/AccountSetupIncoming.java
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity.setup;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.text.method.DigitsKeyListener;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.Spinner;
-import android.widget.TextView;
-
-import com.android.email.Account;
-import com.android.email.Preferences;
-import com.android.email.R;
-import com.android.email.Utility;
-
-public class AccountSetupIncoming extends Activity implements OnClickListener {
- private static final String EXTRA_ACCOUNT = "account";
- private static final String EXTRA_MAKE_DEFAULT = "makeDefault";
-
- private static final int popPorts[] = {
- 110, 995, 995, 110, 110
- };
- private static final String popSchemes[] = {
- "pop3", "pop3+ssl", "pop3+ssl+", "pop3+tls", "pop3+tls+"
- };
- private static final int imapPorts[] = {
- 143, 993, 993, 143, 143
- };
- private static final String imapSchemes[] = {
- "imap", "imap+ssl", "imap+ssl+", "imap+tls", "imap+tls+"
- };
-
- private int mAccountPorts[];
- private String mAccountSchemes[];
- private EditText mUsernameView;
- private EditText mPasswordView;
- private EditText mServerView;
- private EditText mPortView;
- private Spinner mSecurityTypeView;
- private Spinner mDeletePolicyView;
- private EditText mImapPathPrefixView;
- private Button mNextButton;
- private Account mAccount;
- private boolean mMakeDefault;
-
- public static void actionIncomingSettings(Activity context, Account account, boolean makeDefault) {
- Intent i = new Intent(context, AccountSetupIncoming.class);
- i.putExtra(EXTRA_ACCOUNT, account);
- i.putExtra(EXTRA_MAKE_DEFAULT, makeDefault);
- context.startActivity(i);
- }
-
- public static void actionEditIncomingSettings(Activity context, Account account) {
- Intent i = new Intent(context, AccountSetupIncoming.class);
- i.setAction(Intent.ACTION_EDIT);
- i.putExtra(EXTRA_ACCOUNT, account);
- context.startActivity(i);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.account_setup_incoming);
-
- mUsernameView = (EditText)findViewById(R.id.account_username);
- mPasswordView = (EditText)findViewById(R.id.account_password);
- TextView serverLabelView = (TextView) findViewById(R.id.account_server_label);
- mServerView = (EditText)findViewById(R.id.account_server);
- mPortView = (EditText)findViewById(R.id.account_port);
- mSecurityTypeView = (Spinner)findViewById(R.id.account_security_type);
- mDeletePolicyView = (Spinner)findViewById(R.id.account_delete_policy);
- mImapPathPrefixView = (EditText)findViewById(R.id.imap_path_prefix);
- mNextButton = (Button)findViewById(R.id.next);
-
- mNextButton.setOnClickListener(this);
-
- SpinnerOption securityTypes[] = {
- new SpinnerOption(0, getString(R.string.account_setup_incoming_security_none_label)),
- new SpinnerOption(1,
- getString(R.string.account_setup_incoming_security_ssl_optional_label)),
- new SpinnerOption(2, getString(R.string.account_setup_incoming_security_ssl_label)),
- new SpinnerOption(3,
- getString(R.string.account_setup_incoming_security_tls_optional_label)),
- new SpinnerOption(4, getString(R.string.account_setup_incoming_security_tls_label)),
- };
-
- SpinnerOption deletePolicies[] = {
- new SpinnerOption(0,
- getString(R.string.account_setup_incoming_delete_policy_never_label)),
- new SpinnerOption(1,
- getString(R.string.account_setup_incoming_delete_policy_7days_label)),
- new SpinnerOption(2,
- getString(R.string.account_setup_incoming_delete_policy_delete_label)),
- };
-
- ArrayAdapter<SpinnerOption> securityTypesAdapter = new ArrayAdapter<SpinnerOption>(this,
- android.R.layout.simple_spinner_item, securityTypes);
- securityTypesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- mSecurityTypeView.setAdapter(securityTypesAdapter);
-
- ArrayAdapter<SpinnerOption> deletePoliciesAdapter = new ArrayAdapter<SpinnerOption>(this,
- android.R.layout.simple_spinner_item, deletePolicies);
- deletePoliciesAdapter
- .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- mDeletePolicyView.setAdapter(deletePoliciesAdapter);
-
- /*
- * Updates the port when the user changes the security type. This allows
- * us to show a reasonable default which the user can change.
- */
- mSecurityTypeView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3) {
- updatePortFromSecurityType();
- }
-
- public void onNothingSelected(AdapterView<?> arg0) {
- }
- });
-
- /*
- * Calls validateFields() which enables or disables the Next button
- * based on the fields' validity.
- */
- TextWatcher validationTextWatcher = new TextWatcher() {
- public void afterTextChanged(Editable s) {
- validateFields();
- }
-
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
- };
- mUsernameView.addTextChangedListener(validationTextWatcher);
- mPasswordView.addTextChangedListener(validationTextWatcher);
- mServerView.addTextChangedListener(validationTextWatcher);
- mPortView.addTextChangedListener(validationTextWatcher);
-
- /*
- * Only allow digits in the port field.
- */
- mPortView.setKeyListener(DigitsKeyListener.getInstance("0123456789"));
-
- mAccount = (Account)getIntent().getSerializableExtra(EXTRA_ACCOUNT);
- mMakeDefault = getIntent().getBooleanExtra(EXTRA_MAKE_DEFAULT, false);
-
- /*
- * If we're being reloaded we override the original account with the one
- * we saved
- */
- if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_ACCOUNT)) {
- mAccount = (Account)savedInstanceState.getSerializable(EXTRA_ACCOUNT);
- }
-
- try {
- URI uri = new URI(mAccount.getStoreUri());
- String username = null;
- String password = null;
- if (uri.getUserInfo() != null) {
- String[] userInfoParts = uri.getUserInfo().split(":", 2);
- username = userInfoParts[0];
- if (userInfoParts.length > 1) {
- password = userInfoParts[1];
- }
- }
-
- if (username != null) {
- mUsernameView.setText(username);
- }
-
- if (password != null) {
- mPasswordView.setText(password);
- }
-
- if (uri.getScheme().startsWith("pop3")) {
- serverLabelView.setText(R.string.account_setup_incoming_pop_server_label);
- mAccountPorts = popPorts;
- mAccountSchemes = popSchemes;
-
- findViewById(R.id.imap_path_prefix_section).setVisibility(View.GONE);
- } else if (uri.getScheme().startsWith("imap")) {
- serverLabelView.setText(R.string.account_setup_incoming_imap_server_label);
- mAccountPorts = imapPorts;
- mAccountSchemes = imapSchemes;
-
- findViewById(R.id.account_delete_policy_label).setVisibility(View.GONE);
- mDeletePolicyView.setVisibility(View.GONE);
- if (uri.getPath() != null && uri.getPath().length() > 0) {
- mImapPathPrefixView.setText(uri.getPath().substring(1));
- }
- } else {
- throw new Error("Unknown account type: " + mAccount.getStoreUri());
- }
-
- for (int i = 0; i < mAccountSchemes.length; i++) {
- if (mAccountSchemes[i].equals(uri.getScheme())) {
- SpinnerOption.setSpinnerOptionValue(mSecurityTypeView, i);
- }
- }
-
- SpinnerOption.setSpinnerOptionValue(mDeletePolicyView, mAccount.getDeletePolicy());
-
- if (uri.getHost() != null) {
- mServerView.setText(uri.getHost());
- }
-
- if (uri.getPort() != -1) {
- mPortView.setText(Integer.toString(uri.getPort()));
- } else {
- updatePortFromSecurityType();
- }
- } catch (URISyntaxException use) {
- /*
- * We should always be able to parse our own settings.
- */
- throw new Error(use);
- }
-
- validateFields();
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putSerializable(EXTRA_ACCOUNT, mAccount);
- }
-
- /**
- * Check the values in the fields and decide if it makes sense to enable the "next" button
- * NOTE: Does it make sense to extract & combine with similar code in AccountSetupIncoming?
- */
- private void validateFields() {
- boolean enabled = Utility.requiredFieldValid(mUsernameView)
- && Utility.requiredFieldValid(mPasswordView)
- && Utility.requiredFieldValid(mServerView)
- && Utility.requiredFieldValid(mPortView);
- if (enabled) {
- try {
- URI uri = getUri();
- } catch (URISyntaxException use) {
- enabled = false;
- }
- }
- mNextButton.setEnabled(enabled);
- Utility.setCompoundDrawablesAlpha(mNextButton, enabled ? 255 : 128);
- }
-
- private void updatePortFromSecurityType() {
- int securityType = (Integer)((SpinnerOption)mSecurityTypeView.getSelectedItem()).value;
- mPortView.setText(Integer.toString(mAccountPorts[securityType]));
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (resultCode == RESULT_OK) {
- if (Intent.ACTION_EDIT.equals(getIntent().getAction())) {
- mAccount.save(Preferences.getPreferences(this));
- finish();
- } else {
- /*
- * Set the username and password for the outgoing settings to the username and
- * password the user just set for incoming.
- */
- try {
- URI oldUri = new URI(mAccount.getSenderUri());
- URI uri = new URI(
- oldUri.getScheme(),
- mUsernameView.getText().toString().trim() + ":"
- + mPasswordView.getText().toString().trim(),
- oldUri.getHost(),
- oldUri.getPort(),
- null,
- null,
- null);
- mAccount.setSenderUri(uri.toString());
- } catch (URISyntaxException use) {
- /*
- * If we can't set up the URL we just continue. It's only for
- * convenience.
- */
- }
-
-
- AccountSetupOutgoing.actionOutgoingSettings(this, mAccount, mMakeDefault);
- finish();
- }
- }
- }
-
- /**
- * Attempt to create a URI from the fields provided. Throws URISyntaxException if there's
- * a problem with the user input.
- * @return a URI built from the account setup fields
- */
- private URI getUri() throws URISyntaxException {
- int securityType = (Integer)((SpinnerOption)mSecurityTypeView.getSelectedItem()).value;
- String path = null;
- if (mAccountSchemes[securityType].startsWith("imap")) {
- path = "/" + mImapPathPrefixView.getText().toString().trim();
- }
- URI uri = new URI(
- mAccountSchemes[securityType],
- mUsernameView.getText().toString().trim() + ":" +
- mPasswordView.getText().toString().trim(),
- mServerView.getText().toString().trim(),
- Integer.parseInt(mPortView.getText().toString().trim()),
- path, // path
- null, // query
- null);
-
- return uri;
- }
-
- private void onNext() {
- try {
- URI uri = getUri();
- mAccount.setStoreUri(uri.toString());
- } catch (URISyntaxException use) {
- /*
- * It's unrecoverable if we cannot create a URI from components that
- * we validated to be safe.
- */
- throw new Error(use);
- }
-
- mAccount.setDeletePolicy((Integer)((SpinnerOption)mDeletePolicyView.getSelectedItem()).value);
- AccountSetupCheckSettings.actionCheckSettings(this, mAccount, true, false);
- }
-
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.next:
- onNext();
- break;
- }
- }
-}
diff --git a/src/com/android/email/activity/setup/AccountSetupNames.java b/src/com/android/email/activity/setup/AccountSetupNames.java
deleted file mode 100644
index ff1bd0e62..000000000
--- a/src/com/android/email/activity/setup/AccountSetupNames.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity.setup;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.text.method.TextKeyListener;
-import android.text.method.TextKeyListener.Capitalize;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.EditText;
-
-import com.android.email.Account;
-import com.android.email.Email;
-import com.android.email.Preferences;
-import com.android.email.R;
-import com.android.email.Utility;
-import com.android.email.activity.FolderMessageList;
-
-public class AccountSetupNames extends Activity implements OnClickListener {
- private static final String EXTRA_ACCOUNT = "account";
-
- private EditText mDescription;
-
- private EditText mName;
-
- private Account mAccount;
-
- private Button mDoneButton;
-
- public static void actionSetNames(Context context, Account account) {
- Intent i = new Intent(context, AccountSetupNames.class);
- i.putExtra(EXTRA_ACCOUNT, account);
- context.startActivity(i);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.account_setup_names);
- mDescription = (EditText)findViewById(R.id.account_description);
- mName = (EditText)findViewById(R.id.account_name);
- mDoneButton = (Button)findViewById(R.id.done);
- mDoneButton.setOnClickListener(this);
-
- TextWatcher validationTextWatcher = new TextWatcher() {
- public void afterTextChanged(Editable s) {
- validateFields();
- }
-
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
- };
- mName.addTextChangedListener(validationTextWatcher);
-
- mName.setKeyListener(TextKeyListener.getInstance(false, Capitalize.WORDS));
-
- mAccount = (Account)getIntent().getSerializableExtra(EXTRA_ACCOUNT);
-
- /*
- * Since this field is considered optional, we don't set this here. If
- * the user fills in a value we'll reset the current value, otherwise we
- * just leave the saved value alone.
- */
- // mDescription.setText(mAccount.getDescription());
- if (mAccount.getName() != null) {
- mName.setText(mAccount.getName());
- }
- if (!Utility.requiredFieldValid(mName)) {
- mDoneButton.setEnabled(false);
- }
- }
-
- /**
- * TODO: Validator should also trim the name string before checking it.
- */
- private void validateFields() {
- mDoneButton.setEnabled(Utility.requiredFieldValid(mName));
- Utility.setCompoundDrawablesAlpha(mDoneButton, mDoneButton.isEnabled() ? 255 : 128);
- }
-
- /**
- * TODO: Validator should also trim the description string before checking it.
- */
- private void onNext() {
- if (Utility.requiredFieldValid(mDescription)) {
- mAccount.setDescription(mDescription.getText().toString());
- }
- mAccount.setName(mName.getText().toString());
- mAccount.save(Preferences.getPreferences(this));
- FolderMessageList.actionHandleAccount(this, mAccount, Email.INBOX);
- finish();
- }
-
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.done:
- onNext();
- break;
- }
- }
-}
diff --git a/src/com/android/email/activity/setup/AccountSetupOptions.java b/src/com/android/email/activity/setup/AccountSetupOptions.java
deleted file mode 100644
index 04fddd521..000000000
--- a/src/com/android/email/activity/setup/AccountSetupOptions.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity.setup;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.ArrayAdapter;
-import android.widget.CheckBox;
-import android.widget.Spinner;
-
-import com.android.email.Account;
-import com.android.email.Email;
-import com.android.email.Preferences;
-import com.android.email.R;
-
-public class AccountSetupOptions extends Activity implements OnClickListener {
- private static final String EXTRA_ACCOUNT = "account";
-
- private static final String EXTRA_MAKE_DEFAULT = "makeDefault";
-
- private Spinner mCheckFrequencyView;
-
- private CheckBox mDefaultView;
-
- private CheckBox mNotifyView;
-
- private Account mAccount;
-
- public static void actionOptions(Context context, Account account, boolean makeDefault) {
- Intent i = new Intent(context, AccountSetupOptions.class);
- i.putExtra(EXTRA_ACCOUNT, account);
- i.putExtra(EXTRA_MAKE_DEFAULT, makeDefault);
- context.startActivity(i);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.account_setup_options);
-
- mCheckFrequencyView = (Spinner)findViewById(R.id.account_check_frequency);
- mDefaultView = (CheckBox)findViewById(R.id.account_default);
- mNotifyView = (CheckBox)findViewById(R.id.account_notify);
-
- findViewById(R.id.next).setOnClickListener(this);
-
- // NOTE: If you change these values, confirm that the new intervals exist in arrays.xml
- // NOTE: It would be cleaner if the numeric values were obtained from the
- // account_settings_check_frequency_values, array, so the options could be controlled
- // entirely via XML.
- SpinnerOption checkFrequencies[] = {
- new SpinnerOption(-1,
- getString(R.string.account_setup_options_mail_check_frequency_never)),
- new SpinnerOption(5,
- getString(R.string.account_setup_options_mail_check_frequency_5min)),
- new SpinnerOption(10,
- getString(R.string.account_setup_options_mail_check_frequency_10min)),
- new SpinnerOption(15,
- getString(R.string.account_setup_options_mail_check_frequency_15min)),
- new SpinnerOption(30,
- getString(R.string.account_setup_options_mail_check_frequency_30min)),
- new SpinnerOption(60,
- getString(R.string.account_setup_options_mail_check_frequency_1hour)),
- };
-
- ArrayAdapter<SpinnerOption> checkFrequenciesAdapter = new ArrayAdapter<SpinnerOption>(this,
- android.R.layout.simple_spinner_item, checkFrequencies);
- checkFrequenciesAdapter
- .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- mCheckFrequencyView.setAdapter(checkFrequenciesAdapter);
-
- mAccount = (Account)getIntent().getSerializableExtra(EXTRA_ACCOUNT);
- boolean makeDefault = getIntent().getBooleanExtra(EXTRA_MAKE_DEFAULT, false);
-
- if (mAccount.equals(Preferences.getPreferences(this).getDefaultAccount()) || makeDefault) {
- mDefaultView.setChecked(true);
- }
- mNotifyView.setChecked(mAccount.isNotifyNewMail());
- SpinnerOption.setSpinnerOptionValue(mCheckFrequencyView, mAccount
- .getAutomaticCheckIntervalMinutes());
- }
-
- private void onDone() {
- mAccount.setDescription(mAccount.getEmail());
- mAccount.setNotifyNewMail(mNotifyView.isChecked());
- mAccount.setAutomaticCheckIntervalMinutes((Integer)((SpinnerOption)mCheckFrequencyView
- .getSelectedItem()).value);
- mAccount.save(Preferences.getPreferences(this));
- if (mDefaultView.isChecked()) {
- Preferences.getPreferences(this).setDefaultAccount(mAccount);
- }
- Email.setServicesEnabled(this);
- AccountSetupNames.actionSetNames(this, mAccount);
- finish();
- }
-
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.next:
- onDone();
- break;
- }
- }
-}
diff --git a/src/com/android/email/activity/setup/AccountSetupOutgoing.java b/src/com/android/email/activity/setup/AccountSetupOutgoing.java
deleted file mode 100644
index f08835c9c..000000000
--- a/src/com/android/email/activity/setup/AccountSetupOutgoing.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity.setup;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.text.method.DigitsKeyListener;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.View.OnClickListener;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
-import android.widget.EditText;
-import android.widget.Spinner;
-import android.widget.CompoundButton.OnCheckedChangeListener;
-
-import com.android.email.Account;
-import com.android.email.Preferences;
-import com.android.email.R;
-import com.android.email.Utility;
-
-public class AccountSetupOutgoing extends Activity implements OnClickListener,
- OnCheckedChangeListener {
- private static final String EXTRA_ACCOUNT = "account";
-
- private static final String EXTRA_MAKE_DEFAULT = "makeDefault";
-
- private static final int smtpPorts[] = {
- 25, 465, 465, 25, 25
- };
-
- private static final String smtpSchemes[] = {
- "smtp", "smtp+ssl", "smtp+ssl+", "smtp+tls", "smtp+tls+"
- };
-
- private EditText mUsernameView;
- private EditText mPasswordView;
- private EditText mServerView;
- private EditText mPortView;
- private CheckBox mRequireLoginView;
- private ViewGroup mRequireLoginSettingsView;
- private Spinner mSecurityTypeView;
- private Button mNextButton;
- private Account mAccount;
- private boolean mMakeDefault;
-
- public static void actionOutgoingSettings(Context context, Account account, boolean makeDefault) {
- Intent i = new Intent(context, AccountSetupOutgoing.class);
- i.putExtra(EXTRA_ACCOUNT, account);
- i.putExtra(EXTRA_MAKE_DEFAULT, makeDefault);
- context.startActivity(i);
- }
-
- public static void actionEditOutgoingSettings(Context context, Account account) {
- Intent i = new Intent(context, AccountSetupOutgoing.class);
- i.setAction(Intent.ACTION_EDIT);
- i.putExtra(EXTRA_ACCOUNT, account);
- context.startActivity(i);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.account_setup_outgoing);
-
- mUsernameView = (EditText)findViewById(R.id.account_username);
- mPasswordView = (EditText)findViewById(R.id.account_password);
- mServerView = (EditText)findViewById(R.id.account_server);
- mPortView = (EditText)findViewById(R.id.account_port);
- mRequireLoginView = (CheckBox)findViewById(R.id.account_require_login);
- mRequireLoginSettingsView = (ViewGroup)findViewById(R.id.account_require_login_settings);
- mSecurityTypeView = (Spinner)findViewById(R.id.account_security_type);
- mNextButton = (Button)findViewById(R.id.next);
-
- mNextButton.setOnClickListener(this);
- mRequireLoginView.setOnCheckedChangeListener(this);
-
- SpinnerOption securityTypes[] = {
- new SpinnerOption(0, getString(R.string.account_setup_incoming_security_none_label)),
- new SpinnerOption(1,
- getString(R.string.account_setup_incoming_security_ssl_optional_label)),
- new SpinnerOption(2, getString(R.string.account_setup_incoming_security_ssl_label)),
- new SpinnerOption(3,
- getString(R.string.account_setup_incoming_security_tls_optional_label)),
- new SpinnerOption(4, getString(R.string.account_setup_incoming_security_tls_label)),
- };
-
- ArrayAdapter<SpinnerOption> securityTypesAdapter = new ArrayAdapter<SpinnerOption>(this,
- android.R.layout.simple_spinner_item, securityTypes);
- securityTypesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- mSecurityTypeView.setAdapter(securityTypesAdapter);
-
- /*
- * Updates the port when the user changes the security type. This allows
- * us to show a reasonable default which the user can change.
- */
- mSecurityTypeView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3) {
- updatePortFromSecurityType();
- }
-
- public void onNothingSelected(AdapterView<?> arg0) {
- }
- });
-
- /*
- * Calls validateFields() which enables or disables the Next button
- * based on the fields' validity.
- */
- TextWatcher validationTextWatcher = new TextWatcher() {
- public void afterTextChanged(Editable s) {
- validateFields();
- }
-
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
- };
- mUsernameView.addTextChangedListener(validationTextWatcher);
- mPasswordView.addTextChangedListener(validationTextWatcher);
- mServerView.addTextChangedListener(validationTextWatcher);
- mPortView.addTextChangedListener(validationTextWatcher);
-
- /*
- * Only allow digits in the port field.
- */
- mPortView.setKeyListener(DigitsKeyListener.getInstance("0123456789"));
-
- mAccount = (Account)getIntent().getSerializableExtra(EXTRA_ACCOUNT);
- mMakeDefault = (boolean)getIntent().getBooleanExtra(EXTRA_MAKE_DEFAULT, false);
-
- /*
- * If we're being reloaded we override the original account with the one
- * we saved
- */
- if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_ACCOUNT)) {
- mAccount = (Account)savedInstanceState.getSerializable(EXTRA_ACCOUNT);
- }
-
- try {
- URI uri = new URI(mAccount.getSenderUri());
- String username = null;
- String password = null;
- if (uri.getUserInfo() != null) {
- String[] userInfoParts = uri.getUserInfo().split(":", 2);
- username = userInfoParts[0];
- if (userInfoParts.length > 1) {
- password = userInfoParts[1];
- }
- }
-
- if (username != null) {
- mUsernameView.setText(username);
- mRequireLoginView.setChecked(true);
- }
-
- if (password != null) {
- mPasswordView.setText(password);
- }
-
- for (int i = 0; i < smtpSchemes.length; i++) {
- if (smtpSchemes[i].equals(uri.getScheme())) {
- SpinnerOption.setSpinnerOptionValue(mSecurityTypeView, i);
- }
- }
-
- if (uri.getHost() != null) {
- mServerView.setText(uri.getHost());
- }
-
- if (uri.getPort() != -1) {
- mPortView.setText(Integer.toString(uri.getPort()));
- } else {
- updatePortFromSecurityType();
- }
- } catch (URISyntaxException use) {
- /*
- * We should always be able to parse our own settings.
- */
- throw new Error(use);
- }
-
- validateFields();
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putSerializable(EXTRA_ACCOUNT, mAccount);
- }
-
- /**
- * Preflight the values in the fields and decide if it makes sense to enable the "next" button
- * NOTE: Does it make sense to extract & combine with similar code in AccountSetupIncoming?
- */
- private void validateFields() {
- boolean enabled =
- Utility.requiredFieldValid(mServerView) && Utility.requiredFieldValid(mPortView);
-
- if (enabled && mRequireLoginView.isChecked()) {
- enabled = (Utility.requiredFieldValid(mUsernameView)
- && Utility.requiredFieldValid(mPasswordView));
- }
-
- if (enabled) {
- try {
- URI uri = getUri();
- } catch (URISyntaxException use) {
- enabled = false;
- }
- }
- mNextButton.setEnabled(enabled);
- Utility.setCompoundDrawablesAlpha(mNextButton, enabled ? 255 : 128);
- }
-
- private void updatePortFromSecurityType() {
- int securityType = (Integer)((SpinnerOption)mSecurityTypeView.getSelectedItem()).value;
- mPortView.setText(Integer.toString(smtpPorts[securityType]));
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (resultCode == RESULT_OK) {
- if (Intent.ACTION_EDIT.equals(getIntent().getAction())) {
- mAccount.save(Preferences.getPreferences(this));
- finish();
- } else {
- AccountSetupOptions.actionOptions(this, mAccount, mMakeDefault);
- finish();
- }
- }
- }
-
- /**
- * Attempt to create a URI from the fields provided. Throws URISyntaxException if there's
- * a problem with the user input.
- * @return a URI built from the account setup fields
- */
- private URI getUri() throws URISyntaxException {
- int securityType = (Integer)((SpinnerOption)mSecurityTypeView.getSelectedItem()).value;
- String userInfo = null;
- if (mRequireLoginView.isChecked()) {
- userInfo = mUsernameView.getText().toString().trim() + ":"
- + mPasswordView.getText().toString().trim();
- }
- URI uri = new URI(
- smtpSchemes[securityType],
- userInfo,
- mServerView.getText().toString().trim(),
- Integer.parseInt(mPortView.getText().toString().trim()),
- null, null, null);
-
- return uri;
- }
-
- private void onNext() {
- try {
- URI uri = getUri();
- mAccount.setSenderUri(uri.toString());
- } catch (URISyntaxException use) {
- /*
- * It's unrecoverable if we cannot create a URI from components that
- * we validated to be safe.
- */
- throw new Error(use);
- }
- AccountSetupCheckSettings.actionCheckSettings(this, mAccount, false, true);
- }
-
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.next:
- onNext();
- break;
- }
- }
-
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- mRequireLoginSettingsView.setVisibility(isChecked ? View.VISIBLE : View.GONE);
- validateFields();
- }
-}
diff --git a/src/com/android/email/activity/setup/SpinnerOption.java b/src/com/android/email/activity/setup/SpinnerOption.java
deleted file mode 100644
index 4e18d9d7b..000000000
--- a/src/com/android/email/activity/setup/SpinnerOption.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity.setup;
-
-import android.widget.Spinner;
-
-public class SpinnerOption {
- public Object value;
-
- public String label;
-
- public static void setSpinnerOptionValue(Spinner spinner, Object value) {
- for (int i = 0, count = spinner.getCount(); i < count; i++) {
- SpinnerOption so = (SpinnerOption)spinner.getItemAtPosition(i);
- if (so.value.equals(value)) {
- spinner.setSelection(i, true);
- return;
- }
- }
- }
-
- public SpinnerOption(Object value, String label) {
- this.value = value;
- this.label = label;
- }
-
- @Override
- public String toString() {
- return label;
- }
-}
diff --git a/src/com/android/email/codec/binary/Base64.java b/src/com/android/email/codec/binary/Base64.java
deleted file mode 100644
index 3f65c5811..000000000
--- a/src/com/android/email/codec/binary/Base64.java
+++ /dev/null
@@ -1,801 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.codec.binary;
-
-import org.apache.commons.codec.BinaryDecoder;
-import org.apache.commons.codec.BinaryEncoder;
-import org.apache.commons.codec.DecoderException;
-import org.apache.commons.codec.EncoderException;
-
-import java.io.UnsupportedEncodingException;
-import java.math.BigInteger;
-
-/**
- * Provides Base64 encoding and decoding as defined by RFC 2045.
- *
- * <p>
- * This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite> from RFC 2045 <cite>Multipurpose
- * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</cite> by Freed and Borenstein.
- * </p>
- *
- * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
- * @author Apache Software Foundation
- * @since 1.0-dev
- * @version $Id$
- */
-public class Base64 implements BinaryEncoder, BinaryDecoder {
- /**
- * Chunk size per RFC 2045 section 6.8.
- *
- * <p>
- * The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any
- * equal signs.
- * </p>
- *
- * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 6.8</a>
- */
- static final int CHUNK_SIZE = 76;
-
- /**
- * Chunk separator per RFC 2045 section 2.1.
- *
- * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
- */
- static final byte[] CHUNK_SEPARATOR = {'\r','\n'};
-
- /**
- * This array is a lookup table that translates 6-bit positive integer
- * index values into their "Base64 Alphabet" equivalents as specified
- * in Table 1 of RFC 2045.
- *
- * Thanks to "commons" project in ws.apache.org for this code.
- * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
- */
- private static final byte[] intToBase64 = {
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
- 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
- };
-
- /**
- * Byte used to pad output.
- */
- private static final byte PAD = '=';
-
- /**
- * This array is a lookup table that translates unicode characters
- * drawn from the "Base64 Alphabet" (as specified in Table 1 of RFC 2045)
- * into their 6-bit positive integer equivalents. Characters that
- * are not in the Base64 alphabet but fall within the bounds of the
- * array are translated to -1.
- *
- * Thanks to "commons" project in ws.apache.org for this code.
- * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
- */
- private static final byte[] base64ToInt = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
- 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
- };
-
- /** Mask used to extract 6 bits, used when encoding */
- private static final int MASK_6BITS = 0x3f;
-
- /** Mask used to extract 8 bits, used in decoding base64 bytes */
- private static final int MASK_8BITS = 0xff;
-
- // The static final fields above are used for the original static byte[] methods on Base64.
- // The private member fields below are used with the new streaming approach, which requires
- // some state be preserved between calls of encode() and decode().
-
-
- /**
- * Line length for encoding. Not used when decoding. A value of zero or less implies
- * no chunking of the base64 encoded data.
- */
- private final int lineLength;
-
- /**
- * Line separator for encoding. Not used when decoding. Only used if lineLength > 0.
- */
- private final byte[] lineSeparator;
-
- /**
- * Convenience variable to help us determine when our buffer is going to run out of
- * room and needs resizing. <code>decodeSize = 3 + lineSeparator.length;</code>
- */
- private final int decodeSize;
-
- /**
- * Convenience variable to help us determine when our buffer is going to run out of
- * room and needs resizing. <code>encodeSize = 4 + lineSeparator.length;</code>
- */
- private final int encodeSize;
-
- /**
- * Buffer for streaming.
- */
- private byte[] buf;
-
- /**
- * Position where next character should be written in the buffer.
- */
- private int pos;
-
- /**
- * Position where next character should be read from the buffer.
- */
- private int readPos;
-
- /**
- * Variable tracks how many characters have been written to the current line.
- * Only used when encoding. We use it to make sure each encoded line never
- * goes beyond lineLength (if lineLength > 0).
- */
- private int currentLinePos;
-
- /**
- * Writes to the buffer only occur after every 3 reads when encoding, an
- * every 4 reads when decoding. This variable helps track that.
- */
- private int modulus;
-
- /**
- * Boolean flag to indicate the EOF has been reached. Once EOF has been
- * reached, this Base64 object becomes useless, and must be thrown away.
- */
- private boolean eof;
-
- /**
- * Place holder for the 3 bytes we're dealing with for our base64 logic.
- * Bitwise operations store and extract the base64 encoding or decoding from
- * this variable.
- */
- private int x;
-
- /**
- * Default constructor: lineLength is 76, and the lineSeparator is CRLF
- * when encoding, and all forms can be decoded.
- */
- public Base64() {
- this(CHUNK_SIZE, CHUNK_SEPARATOR);
- }
-
- /**
- * <p>
- * Consumer can use this constructor to choose a different lineLength
- * when encoding (lineSeparator is still CRLF). All forms of data can
- * be decoded.
- * </p><p>
- * Note: lineLengths that aren't multiples of 4 will still essentially
- * end up being multiples of 4 in the encoded data.
- * </p>
- *
- * @param lineLength each line of encoded data will be at most this long
- * (rounded up to nearest multiple of 4).
- * If lineLength <= 0, then the output will not be divided into lines (chunks).
- * Ignored when decoding.
- */
- public Base64(int lineLength) {
- this(lineLength, CHUNK_SEPARATOR);
- }
-
- /**
- * <p>
- * Consumer can use this constructor to choose a different lineLength
- * and lineSeparator when encoding. All forms of data can
- * be decoded.
- * </p><p>
- * Note: lineLengths that aren't multiples of 4 will still essentially
- * end up being multiples of 4 in the encoded data.
- * </p>
- * @param lineLength Each line of encoded data will be at most this long
- * (rounded up to nearest multiple of 4). Ignored when decoding.
- * If <= 0, then output will not be divided into lines (chunks).
- * @param lineSeparator Each line of encoded data will end with this
- * sequence of bytes.
- * If lineLength <= 0, then the lineSeparator is not used.
- * @throws IllegalArgumentException The provided lineSeparator included
- * some base64 characters. That's not going to work!
- */
- public Base64(int lineLength, byte[] lineSeparator) {
- this.lineLength = lineLength;
- this.lineSeparator = new byte[lineSeparator.length];
- System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length);
- if (lineLength > 0) {
- this.encodeSize = 4 + lineSeparator.length;
- } else {
- this.encodeSize = 4;
- }
- this.decodeSize = encodeSize - 1;
- if (containsBase64Byte(lineSeparator)) {
- String sep;
- try {
- sep = new String(lineSeparator, "UTF-8");
- } catch (UnsupportedEncodingException uee) {
- sep = new String(lineSeparator);
- }
- throw new IllegalArgumentException("lineSeperator must not contain base64 characters: [" + sep + "]");
- }
- }
-
- /**
- * Returns true if this Base64 object has buffered data for reading.
- *
- * @return true if there is Base64 object still available for reading.
- */
- boolean hasData() { return buf != null; }
-
- /**
- * Returns the amount of buffered data available for reading.
- *
- * @return The amount of buffered data available for reading.
- */
- int avail() { return buf != null ? pos - readPos : 0; }
-
- /** Doubles our buffer. */
- private void resizeBuf() {
- if (buf == null) {
- buf = new byte[8192];
- pos = 0;
- readPos = 0;
- } else {
- byte[] b = new byte[buf.length * 2];
- System.arraycopy(buf, 0, b, 0, buf.length);
- buf = b;
- }
- }
-
- /**
- * Extracts buffered data into the provided byte[] array, starting
- * at position bPos, up to a maximum of bAvail bytes. Returns how
- * many bytes were actually extracted.
- *
- * @param b byte[] array to extract the buffered data into.
- * @param bPos position in byte[] array to start extraction at.
- * @param bAvail amount of bytes we're allowed to extract. We may extract
- * fewer (if fewer are available).
- * @return The number of bytes successfully extracted into the provided
- * byte[] array.
- */
- int readResults(byte[] b, int bPos, int bAvail) {
- if (buf != null) {
- int len = Math.min(avail(), bAvail);
- if (buf != b) {
- System.arraycopy(buf, readPos, b, bPos, len);
- readPos += len;
- if (readPos >= pos) {
- buf = null;
- }
- } else {
- // Re-using the original consumer's output array is only
- // allowed for one round.
- buf = null;
- }
- return len;
- } else {
- return eof ? -1 : 0;
- }
- }
-
- /**
- * Small optimization where we try to buffer directly to the consumer's
- * output array for one round (if consumer calls this method first!) instead
- * of starting our own buffer.
- *
- * @param out byte[] array to buffer directly to.
- * @param outPos Position to start buffering into.
- * @param outAvail Amount of bytes available for direct buffering.
- */
- void setInitialBuffer(byte[] out, int outPos, int outAvail) {
- // We can re-use consumer's original output array under
- // special circumstances, saving on some System.arraycopy().
- if (out != null && out.length == outAvail) {
- buf = out;
- pos = outPos;
- readPos = outPos;
- }
- }
-
- /**
- * <p>
- * Encodes all of the provided data, starting at inPos, for inAvail bytes.
- * Must be called at least twice: once with the data to encode, and once
- * with inAvail set to "-1" to alert encoder that EOF has been reached,
- * so flush last remaining bytes (if not multiple of 3).
- * </p><p>
- * Thanks to "commons" project in ws.apache.org for the bitwise operations,
- * and general approach.
- * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
- * </p>
- *
- * @param in byte[] array of binary data to base64 encode.
- * @param inPos Position to start reading data from.
- * @param inAvail Amount of bytes available from input for encoding.
- */
- void encode(byte[] in, int inPos, int inAvail) {
- if (eof) {
- return;
- }
-
- // inAvail < 0 is how we're informed of EOF in the underlying data we're
- // encoding.
- if (inAvail < 0) {
- eof = true;
- if (buf == null || buf.length - pos < encodeSize) {
- resizeBuf();
- }
- switch (modulus) {
- case 1:
- buf[pos++] = intToBase64[(x >> 2) & MASK_6BITS];
- buf[pos++] = intToBase64[(x << 4) & MASK_6BITS];
- buf[pos++] = PAD;
- buf[pos++] = PAD;
- break;
-
- case 2:
- buf[pos++] = intToBase64[(x >> 10) & MASK_6BITS];
- buf[pos++] = intToBase64[(x >> 4) & MASK_6BITS];
- buf[pos++] = intToBase64[(x << 2) & MASK_6BITS];
- buf[pos++] = PAD;
- break;
- }
- if (lineLength > 0) {
- System.arraycopy(lineSeparator, 0, buf, pos, lineSeparator.length);
- pos += lineSeparator.length;
- }
- } else {
- for (int i = 0; i < inAvail; i++) {
- if (buf == null || buf.length - pos < encodeSize) {
- resizeBuf();
- }
- modulus = (++modulus) % 3;
- int b = in[inPos++];
- if (b < 0) { b += 256; }
- x = (x << 8) + b;
- if (0 == modulus) {
- buf[pos++] = intToBase64[(x >> 18) & MASK_6BITS];
- buf[pos++] = intToBase64[(x >> 12) & MASK_6BITS];
- buf[pos++] = intToBase64[(x >> 6) & MASK_6BITS];
- buf[pos++] = intToBase64[x & MASK_6BITS];
- currentLinePos += 4;
- if (lineLength > 0 && lineLength <= currentLinePos) {
- System.arraycopy(lineSeparator, 0, buf, pos, lineSeparator.length);
- pos += lineSeparator.length;
- currentLinePos = 0;
- }
- }
- }
- }
- }
-
- /**
- * <p>
- * Decodes all of the provided data, starting at inPos, for inAvail bytes.
- * Should be called at least twice: once with the data to decode, and once
- * with inAvail set to "-1" to alert decoder that EOF has been reached.
- * The "-1" call is not necessary when decoding, but it doesn't hurt, either.
- * </p><p>
- * Ignores all non-base64 characters. This is how chunked (e.g. 76 character)
- * data is handled, since CR and LF are silently ignored, but has implications
- * for other bytes, too. This method subscribes to the garbage-in, garbage-out
- * philosophy: it will not check the provided data for validity.
- * </p><p>
- * Thanks to "commons" project in ws.apache.org for the bitwise operations,
- * and general approach.
- * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
- * </p>
-
- * @param in byte[] array of ascii data to base64 decode.
- * @param inPos Position to start reading data from.
- * @param inAvail Amount of bytes available from input for encoding.
- */
- void decode(byte[] in, int inPos, int inAvail) {
- if (eof) {
- return;
- }
- if (inAvail < 0) {
- eof = true;
- }
- for (int i = 0; i < inAvail; i++) {
- if (buf == null || buf.length - pos < decodeSize) {
- resizeBuf();
- }
- byte b = in[inPos++];
- if (b == PAD) {
- x = x << 6;
- switch (modulus) {
- case 2:
- x = x << 6;
- buf[pos++] = (byte) ((x >> 16) & MASK_8BITS);
- break;
- case 3:
- buf[pos++] = (byte) ((x >> 16) & MASK_8BITS);
- buf[pos++] = (byte) ((x >> 8) & MASK_8BITS);
- break;
- }
- // WE'RE DONE!!!!
- eof = true;
- return;
- } else {
- if (b >= 0 && b < base64ToInt.length) {
- int result = base64ToInt[b];
- if (result >= 0) {
- modulus = (++modulus) % 4;
- x = (x << 6) + result;
- if (modulus == 0) {
- buf[pos++] = (byte) ((x >> 16) & MASK_8BITS);
- buf[pos++] = (byte) ((x >> 8) & MASK_8BITS);
- buf[pos++] = (byte) (x & MASK_8BITS);
- }
- }
- }
- }
- }
- }
-
- /**
- * Returns whether or not the <code>octet</code> is in the base 64 alphabet.
- *
- * @param octet
- * The value to test
- * @return <code>true</code> if the value is defined in the the base 64 alphabet, <code>false</code> otherwise.
- */
- public static boolean isBase64(byte octet) {
- return octet == PAD || (octet >= 0 && octet < base64ToInt.length && base64ToInt[octet] != -1);
- }
-
- /**
- * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet.
- * Currently the method treats whitespace as valid.
- *
- * @param arrayOctet
- * byte array to test
- * @return <code>true</code> if all bytes are valid characters in the Base64 alphabet or if the byte array is
- * empty; false, otherwise
- */
- public static boolean isArrayByteBase64(byte[] arrayOctet) {
- for (int i = 0; i < arrayOctet.length; i++) {
- if (!isBase64(arrayOctet[i]) && !isWhiteSpace(arrayOctet[i])) {
- return false;
- }
- }
- return true;
- }
-
- /*
- * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet.
- *
- * @param arrayOctet
- * byte array to test
- * @return <code>true</code> if any byte is a valid character in the Base64 alphabet; false herwise
- */
- private static boolean containsBase64Byte(byte[] arrayOctet) {
- for (int i = 0; i < arrayOctet.length; i++) {
- if (isBase64(arrayOctet[i])) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Encodes binary data using the base64 algorithm but does not chunk the output.
- *
- * @param binaryData
- * binary data to encode
- * @return Base64 characters
- */
- public static byte[] encodeBase64(byte[] binaryData) {
- return encodeBase64(binaryData, false);
- }
-
- /**
- * Encodes binary data using the base64 algorithm and chunks the encoded output into 76 character blocks
- *
- * @param binaryData
- * binary data to encode
- * @return Base64 characters chunked in 76 character blocks
- */
- public static byte[] encodeBase64Chunked(byte[] binaryData) {
- return encodeBase64(binaryData, true);
- }
-
- /**
- * Decodes an Object using the base64 algorithm. This method is provided in order to satisfy the requirements of the
- * Decoder interface, and will throw a DecoderException if the supplied object is not of type byte[].
- *
- * @param pObject
- * Object to decode
- * @return An object (of type byte[]) containing the binary data which corresponds to the byte[] supplied.
- * @throws DecoderException
- * if the parameter supplied is not of type byte[]
- */
- public Object decode(Object pObject) throws DecoderException {
- if (!(pObject instanceof byte[])) {
- throw new DecoderException("Parameter supplied to Base64 decode is not a byte[]");
- }
- return decode((byte[]) pObject);
- }
-
- /**
- * Decodes a byte[] containing containing characters in the Base64 alphabet.
- *
- * @param pArray
- * A byte array containing Base64 character data
- * @return a byte array containing binary data
- */
- public byte[] decode(byte[] pArray) {
- return decodeBase64(pArray);
- }
-
- /**
- * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
- *
- * @param binaryData
- * Array containing binary data to encode.
- * @param isChunked
- * if <code>true</code> this encoder will chunk the base64 output into 76 character blocks
- * @return Base64-encoded data.
- * @throws IllegalArgumentException
- * Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}
- */
- public static byte[] encodeBase64(byte[] binaryData, boolean isChunked) {
- if (binaryData == null || binaryData.length == 0) {
- return binaryData;
- }
- Base64 b64 = isChunked ? new Base64() : new Base64(0);
-
- long len = (binaryData.length * 4) / 3;
- long mod = len % 4;
- if (mod != 0) {
- len += 4 - mod;
- }
- // If chunked, add space for one CHUNK_SEPARATOR per chunk. (Technically, these are chunk
- // terminators, because even a single chunk message has one.)
- //
- // User length Encoded length Rounded up by 4 Num chunks Final buf len
- // 56 74 76 1 78
- // 57 76 76 1 78
- // 58 77 80 2 84
- // 59 78 80 2 84
- //
- // Or...
- // Rounded up size: 4...76 Chunks: 1
- // Rounded up size: 80..152 Chunks: 2
- // Rounded up size: 156..228 Chunks: 3 ...etc...
- if (isChunked) {
- len += ((len + CHUNK_SIZE - 1) / CHUNK_SIZE) * CHUNK_SEPARATOR.length;
- }
-
- if (len > Integer.MAX_VALUE) {
- throw new IllegalArgumentException(
- "Input array too big, output array would be bigger than Integer.MAX_VALUE=" + Integer.MAX_VALUE);
- }
- byte[] buf = new byte[(int) len];
- b64.setInitialBuffer(buf, 0, buf.length);
- b64.encode(binaryData, 0, binaryData.length);
- b64.encode(binaryData, 0, -1); // Notify encoder of EOF.
-
- // Encoder might have resized, even though it was unnecessary.
- if (b64.buf != buf) {
- b64.readResults(buf, 0, buf.length);
- }
- return buf;
- }
-
- /**
- * Decodes Base64 data into octets
- *
- * @param base64Data Byte array containing Base64 data
- * @return Array containing decoded data.
- */
- public static byte[] decodeBase64(byte[] base64Data) {
- if (base64Data == null || base64Data.length == 0) {
- return base64Data;
- }
- Base64 b64 = new Base64();
-
- long len = (base64Data.length * 3) / 4;
- byte[] buf = new byte[(int) len];
- b64.setInitialBuffer(buf, 0, buf.length);
- b64.decode(base64Data, 0, base64Data.length);
- b64.decode(base64Data, 0, -1); // Notify decoder of EOF.
-
- // We have no idea what the line-length was, so we
- // cannot know how much of our array wasn't used.
- byte[] result = new byte[b64.pos];
- b64.readResults(result, 0, result.length);
- return result;
- }
-
- /**
- * Discards any whitespace from a base-64 encoded block.
- *
- * @param data
- * The base-64 encoded data to discard the whitespace from.
- * @return The data, less whitespace (see RFC 2045).
- * @deprecated This method is no longer needed
- */
- static byte[] discardWhitespace(byte[] data) {
- byte groomedData[] = new byte[data.length];
- int bytesCopied = 0;
-
- for (int i = 0; i < data.length; i++) {
- switch (data[i]) {
- case ' ' :
- case '\n' :
- case '\r' :
- case '\t' :
- break;
- default :
- groomedData[bytesCopied++] = data[i];
- }
- }
-
- byte packedData[] = new byte[bytesCopied];
-
- System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
-
- return packedData;
- }
-
-
- /**
- * Check if a byte value is whitespace or not.
- *
- * @param byteToCheck the byte to check
- * @return true if byte is whitespace, false otherwise
- */
- private static boolean isWhiteSpace(byte byteToCheck){
- switch (byteToCheck) {
- case ' ' :
- case '\n' :
- case '\r' :
- case '\t' :
- return true;
- default :
- return false;
- }
- }
-
- /**
- * Discards any characters outside of the base64 alphabet, per the requirements on page 25 of RFC 2045 - "Any
- * characters outside of the base64 alphabet are to be ignored in base64 encoded data."
- *
- * @param data
- * The base-64 encoded data to groom
- * @return The data, less non-base64 characters (see RFC 2045).
- */
- static byte[] discardNonBase64(byte[] data) {
- byte groomedData[] = new byte[data.length];
- int bytesCopied = 0;
-
- for (int i = 0; i < data.length; i++) {
- if (isBase64(data[i])) {
- groomedData[bytesCopied++] = data[i];
- }
- }
-
- byte packedData[] = new byte[bytesCopied];
-
- System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
-
- return packedData;
- }
-
- // Implementation of the Encoder Interface
-
- /**
- * Encodes an Object using the base64 algorithm. This method is provided in order to satisfy the requirements of the
- * Encoder interface, and will throw an EncoderException if the supplied object is not of type byte[].
- *
- * @param pObject
- * Object to encode
- * @return An object (of type byte[]) containing the base64 encoded data which corresponds to the byte[] supplied.
- * @throws EncoderException
- * if the parameter supplied is not of type byte[]
- */
- public Object encode(Object pObject) throws EncoderException {
- if (!(pObject instanceof byte[])) {
- throw new EncoderException("Parameter supplied to Base64 encode is not a byte[]");
- }
- return encode((byte[]) pObject);
- }
-
- /**
- * Encodes a byte[] containing binary data, into a byte[] containing characters in the Base64 alphabet.
- *
- * @param pArray
- * a byte array containing binary data
- * @return A byte array containing only Base64 character data
- */
- public byte[] encode(byte[] pArray) {
- return encodeBase64(pArray, false);
- }
-
- // Implementation of integer encoding used for crypto
- /**
- * Decode a byte64-encoded integer according to crypto
- * standards such as W3C's XML-Signature
- *
- * @param pArray a byte array containing base64 character data
- * @return A BigInteger
- */
- public static BigInteger decodeInteger(byte[] pArray) {
- return new BigInteger(1, decodeBase64(pArray));
- }
-
- /**
- * Encode to a byte64-encoded integer according to crypto
- * standards such as W3C's XML-Signature
- *
- * @param bigInt a BigInteger
- * @return A byte array containing base64 character data
- * @throws NullPointerException if null is passed in
- */
- public static byte[] encodeInteger(BigInteger bigInt) {
- if(bigInt == null) {
- throw new NullPointerException("encodeInteger called with null parameter");
- }
-
- return encodeBase64(toIntegerBytes(bigInt), false);
- }
-
- /**
- * Returns a byte-array representation of a <code>BigInteger</code>
- * without sign bit.
- *
- * @param bigInt <code>BigInteger</code> to be converted
- * @return a byte array representation of the BigInteger parameter
- */
- static byte[] toIntegerBytes(BigInteger bigInt) {
- int bitlen = bigInt.bitLength();
- // round bitlen
- bitlen = ((bitlen + 7) >> 3) << 3;
- byte[] bigBytes = bigInt.toByteArray();
-
- if(((bigInt.bitLength() % 8) != 0) &&
- (((bigInt.bitLength() / 8) + 1) == (bitlen / 8))) {
- return bigBytes;
- }
-
- // set up params for copying everything but sign bit
- int startSrc = 0;
- int len = bigBytes.length;
-
- // if bigInt is exactly byte-aligned, just skip signbit in copy
- if((bigInt.bitLength() % 8) == 0) {
- startSrc = 1;
- len--;
- }
-
- int startDst = bitlen / 8 - len; // to pad w/ nulls as per spec
- byte[] resizedBytes = new byte[bitlen / 8];
-
- System.arraycopy(bigBytes, startSrc, resizedBytes, startDst, len);
-
- return resizedBytes;
- }
-}
diff --git a/src/com/android/email/codec/binary/Base64OutputStream.java b/src/com/android/email/codec/binary/Base64OutputStream.java
deleted file mode 100644
index ba59c3c95..000000000
--- a/src/com/android/email/codec/binary/Base64OutputStream.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.codec.binary;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Provides Base64 encoding and decoding in a streaming fashion (unlimited size).
- * When encoding the default lineLength is 76 characters and the default
- * lineEnding is CRLF, but these can be overridden by using the appropriate
- * constructor.
- * <p>
- * The default behaviour of the Base64OutputStream is to ENCODE, whereas the
- * default behaviour of the Base64InputStream is to DECODE. But this behaviour
- * can be overridden by using a different constructor.
- * </p><p>
- * This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite> from RFC 2045 <cite>Multipurpose
- * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</cite> by Freed and Borenstein.
- * </p>
- *
- * @author Apache Software Foundation
- * @version $Id $
- * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
- * @since 1.0-dev
- */
-public class Base64OutputStream extends FilterOutputStream {
- private final boolean doEncode;
- private final Base64 base64;
- private final byte[] singleByte = new byte[1];
-
- /**
- * Creates a Base64OutputStream such that all data written is Base64-encoded
- * to the original provided OutputStream.
- *
- * @param out OutputStream to wrap.
- */
- public Base64OutputStream(OutputStream out) {
- this(out, true);
- }
-
- /**
- * Creates a Base64OutputStream such that all data written is either
- * Base64-encoded or Base64-decoded to the original provided OutputStream.
- *
- * @param out OutputStream to wrap.
- * @param doEncode true if we should encode all data written to us,
- * false if we should decode.
- */
- public Base64OutputStream(OutputStream out, boolean doEncode) {
- super(out);
- this.doEncode = doEncode;
- this.base64 = new Base64();
- }
-
- /**
- * Creates a Base64OutputStream such that all data written is either
- * Base64-encoded or Base64-decoded to the original provided OutputStream.
- *
- * @param out OutputStream to wrap.
- * @param doEncode true if we should encode all data written to us,
- * false if we should decode.
- * @param lineLength If doEncode is true, each line of encoded
- * data will contain lineLength characters.
- * If lineLength <=0, the encoded data is not divided into lines.
- * If doEncode is false, lineLength is ignored.
- * @param lineSeparator If doEncode is true, each line of encoded
- * data will be terminated with this byte sequence (e.g. \r\n).
- * If lineLength <= 0, the lineSeparator is not used.
- * If doEncode is false lineSeparator is ignored.
- */
- public Base64OutputStream(OutputStream out, boolean doEncode, int lineLength, byte[] lineSeparator) {
- super(out);
- this.doEncode = doEncode;
- this.base64 = new Base64(lineLength, lineSeparator);
- }
-
- /**
- * Writes the specified <code>byte</code> to this output stream.
- */
- public void write(int i) throws IOException {
- singleByte[0] = (byte) i;
- write(singleByte, 0, 1);
- }
-
- /**
- * Writes <code>len</code> bytes from the specified
- * <code>b</code> array starting at <code>offset</code> to
- * this output stream.
- *
- * @param b source byte array
- * @param offset where to start reading the bytes
- * @param len maximum number of bytes to write
- *
- * @throws IOException if an I/O error occurs.
- * @throws NullPointerException if the byte array parameter is null
- * @throws IndexOutOfBoundsException if offset, len or buffer size are invalid
- */
- public void write(byte b[], int offset, int len) throws IOException {
- if (b == null) {
- throw new NullPointerException();
- } else if (offset < 0 || len < 0 || offset + len < 0) {
- throw new IndexOutOfBoundsException();
- } else if (offset > b.length || offset + len > b.length) {
- throw new IndexOutOfBoundsException();
- } else if (len > 0) {
- if (doEncode) {
- base64.encode(b, offset, len);
- } else {
- base64.decode(b, offset, len);
- }
- flush(false);
- }
- }
-
- /**
- * Flushes this output stream and forces any buffered output bytes
- * to be written out to the stream. If propogate is true, the wrapped
- * stream will also be flushed.
- *
- * @param propogate boolean flag to indicate whether the wrapped
- * OutputStream should also be flushed.
- * @throws IOException if an I/O error occurs.
- */
- private void flush(boolean propogate) throws IOException {
- int avail = base64.avail();
- if (avail > 0) {
- byte[] buf = new byte[avail];
- int c = base64.readResults(buf, 0, avail);
- if (c > 0) {
- out.write(buf, 0, c);
- }
- }
- if (propogate) {
- out.flush();
- }
- }
-
- /**
- * Flushes this output stream and forces any buffered output bytes
- * to be written out to the stream.
- *
- * @throws IOException if an I/O error occurs.
- */
- public void flush() throws IOException {
- flush(true);
- }
-
- /**
- * Closes this output stream, flushing any remaining bytes that must be encoded. The
- * underlying stream is flushed but not closed.
- */
- public void close() throws IOException {
- // Notify encoder of EOF (-1).
- if (doEncode) {
- base64.encode(singleByte, 0, -1);
- } else {
- base64.decode(singleByte, 0, -1);
- }
- flush();
- }
-
-}
diff --git a/src/com/android/email/mail/Address.java b/src/com/android/email/mail/Address.java
deleted file mode 100644
index e0851db2d..000000000
--- a/src/com/android/email/mail/Address.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.james.mime4j.field.address.AddressList;
-import org.apache.james.mime4j.field.address.Mailbox;
-import org.apache.james.mime4j.field.address.MailboxList;
-import org.apache.james.mime4j.field.address.NamedMailbox;
-import org.apache.james.mime4j.field.address.parser.ParseException;
-
-import android.util.Config;
-import android.util.Log;
-
-import com.android.email.Email;
-import com.android.email.Utility;
-import com.android.email.mail.internet.MimeUtility;
-
-public class Address {
- String mAddress;
-
- String mPersonal;
-
- public Address(String address, String personal) {
- this.mAddress = address;
- this.mPersonal = personal;
- }
-
- public Address(String address) {
- this.mAddress = address;
- }
-
- public String getAddress() {
- return mAddress;
- }
-
- public void setAddress(String address) {
- this.mAddress = address;
- }
-
- public String getPersonal() {
- return mPersonal;
- }
-
- public void setPersonal(String personal) {
- this.mPersonal = personal;
- }
-
- /**
- * Parse a comma separated list of addresses in RFC-822 format and return an
- * array of Address objects.
- *
- * @param addressList
- * @return An array of 0 or more Addresses.
- */
- public static Address[] parse(String addressList) {
- ArrayList<Address> addresses = new ArrayList<Address>();
- if (addressList == null) {
- return new Address[] {};
- }
- try {
- MailboxList parsedList = AddressList.parse(addressList).flatten();
- for (int i = 0, count = parsedList.size(); i < count; i++) {
- org.apache.james.mime4j.field.address.Address address = parsedList.get(i);
- if (address instanceof NamedMailbox) {
- NamedMailbox namedMailbox = (NamedMailbox)address;
- addresses.add(new Address(namedMailbox.getLocalPart() + "@"
- + namedMailbox.getDomain(), namedMailbox.getName()));
- } else if (address instanceof Mailbox) {
- Mailbox mailbox = (Mailbox)address;
- addresses.add(new Address(mailbox.getLocalPart() + "@" + mailbox.getDomain()));
- } else {
- Log.e(Email.LOG_TAG, "Unknown address type from Mime4J: "
- + address.getClass().toString());
- }
-
- }
- } catch (ParseException pe) {
- }
- return addresses.toArray(new Address[] {});
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof Address) {
- return getAddress().equals(((Address) o).getAddress());
- }
- return super.equals(o);
- }
-
- public String toString() {
- if (mPersonal != null) {
- if (mPersonal.matches(".*[\\(\\)<>@,;:\\\\\".\\[\\]].*")) {
- return Utility.quoteString(mPersonal) + " <" + mAddress + ">";
- } else {
- return mPersonal + " <" + mAddress + ">";
- }
- } else {
- return mAddress;
- }
- }
-
- public static String toString(Address[] addresses) {
- if (addresses == null) {
- return null;
- }
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < addresses.length; i++) {
- sb.append(addresses[i].toString());
- if (i < addresses.length - 1) {
- sb.append(',');
- }
- }
- return sb.toString();
- }
-
- /**
- * @return the personal portion of this Address, or the address portion if the
- * personal portion is not available
- */
- public String toFriendly() {
- if (mPersonal != null && mPersonal.length() > 0) {
- return mPersonal;
- }
- else {
- return mAddress;
- }
- }
-
- /**
- * Creates a comma-delimited list of addresses in the "friendly" format (see toFriendly() for
- * details on the per-address conversion).
- * @param addresses array of Address[] values
- * @return A comma-delimited string listing all of the addresses supplied. Null if source
- * was null or empty.
- */
- public static String toFriendly(Address[] addresses) {
- if (addresses == null || addresses.length == 0) {
- return null;
- }
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < addresses.length; i++) {
- if (i > 0) {
- sb.append(',');
- }
- sb.append(addresses[i].toFriendly());
- }
- return sb.toString();
- }
-
- /**
- * Unpacks an address list previously packed with packAddressList()
- * @param list
- * @return
- */
- public static Address[] unpack(String addressList) {
- if (addressList == null) {
- return new Address[] { };
- }
- ArrayList<Address> addresses = new ArrayList<Address>();
- int length = addressList.length();
- int pairStartIndex = 0;
- int pairEndIndex = 0;
- int addressEndIndex = 0;
- while (pairStartIndex < length) {
- pairEndIndex = addressList.indexOf(',', pairStartIndex);
- if (pairEndIndex == -1) {
- pairEndIndex = length;
- }
- addressEndIndex = addressList.indexOf(';', pairStartIndex);
- String address = null;
- String personal = null;
- if (addressEndIndex == -1 || addressEndIndex > pairEndIndex) {
- address = Utility.fastUrlDecode(addressList.substring(pairStartIndex, pairEndIndex));
- }
- else {
- address = Utility.fastUrlDecode(addressList.substring(pairStartIndex, addressEndIndex));
- personal = Utility.fastUrlDecode(addressList.substring(addressEndIndex + 1, pairEndIndex));
- }
- addresses.add(new Address(address, personal));
- pairStartIndex = pairEndIndex + 1;
- }
- return addresses.toArray(new Address[] { });
- }
-
- /**
- * Packs an address list into a String that is very quick to read
- * and parse. Packed lists can be unpacked with unpackAddressList()
- * The packed list is a comma seperated list of:
- * URLENCODE(address)[;URLENCODE(personal)]
- * @param list
- * @return
- */
- public static String pack(Address[] addresses) {
- if (addresses == null) {
- return null;
- }
- StringBuffer sb = new StringBuffer();
- for (int i = 0, count = addresses.length; i < count; i++) {
- Address address = addresses[i];
- try {
- sb.append(URLEncoder.encode(address.getAddress(), "UTF-8"));
- if (address.getPersonal() != null) {
- sb.append(';');
- sb.append(URLEncoder.encode(address.getPersonal(), "UTF-8"));
- }
- if (i < count - 1) {
- sb.append(',');
- }
- }
- catch (UnsupportedEncodingException uee) {
- return null;
- }
- }
- return sb.toString();
- }
-}
diff --git a/src/com/android/email/mail/AuthenticationFailedException.java b/src/com/android/email/mail/AuthenticationFailedException.java
deleted file mode 100644
index 47e767f5a..000000000
--- a/src/com/android/email/mail/AuthenticationFailedException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-public class AuthenticationFailedException extends MessagingException {
- public static final long serialVersionUID = -1;
-
- public AuthenticationFailedException(String message) {
- super(message);
- }
-
- public AuthenticationFailedException(String message, Throwable throwable) {
- super(message, throwable);
- }
-}
diff --git a/src/com/android/email/mail/Body.java b/src/com/android/email/mail/Body.java
deleted file mode 100644
index a8f27424e..000000000
--- a/src/com/android/email/mail/Body.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-public interface Body {
- public InputStream getInputStream() throws MessagingException;
- public void writeTo(OutputStream out) throws IOException, MessagingException;
-}
diff --git a/src/com/android/email/mail/BodyPart.java b/src/com/android/email/mail/BodyPart.java
deleted file mode 100644
index c650c74ef..000000000
--- a/src/com/android/email/mail/BodyPart.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-public abstract class BodyPart implements Part {
- protected Multipart mParent;
-
- public Multipart getParent() {
- return mParent;
- }
-}
diff --git a/src/com/android/email/mail/CertificateValidationException.java b/src/com/android/email/mail/CertificateValidationException.java
deleted file mode 100644
index d1a95e6f0..000000000
--- a/src/com/android/email/mail/CertificateValidationException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-public class CertificateValidationException extends MessagingException {
- public static final long serialVersionUID = -1;
-
- public CertificateValidationException(String message) {
- super(message);
- }
-
- public CertificateValidationException(String message, Throwable throwable) {
- super(message, throwable);
- }
-} \ No newline at end of file
diff --git a/src/com/android/email/mail/FetchProfile.java b/src/com/android/email/mail/FetchProfile.java
deleted file mode 100644
index e5449e6b8..000000000
--- a/src/com/android/email/mail/FetchProfile.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-import java.util.ArrayList;
-
-/**
- * <pre>
- * A FetchProfile is a list of items that should be downloaded in bulk for a set of messages.
- * FetchProfile can contain the following objects:
- * FetchProfile.Item: Described below.
- * Message: Indicates that the body of the entire message should be fetched.
- * Synonymous with FetchProfile.Item.BODY.
- * Part: Indicates that the given Part should be fetched. The provider
- * is expected have previously created the given BodyPart and stored
- * any information it needs to download the content.
- * </pre>
- */
-public class FetchProfile extends ArrayList {
- /**
- * Default items available for pre-fetching. It should be expected that any
- * item fetched by using these items could potentially include all of the
- * previous items.
- */
- public enum Item {
- /**
- * Download the flags of the message.
- */
- FLAGS,
-
- /**
- * Download the envelope of the message. This should include at minimum
- * the size and the following headers: date, subject, from, content-type, to, cc
- */
- ENVELOPE,
-
- /**
- * Download the structure of the message. This maps directly to IMAP's BODYSTRUCTURE
- * and may map to other providers.
- * The provider should, if possible, fill in a properly formatted MIME structure in
- * the message without actually downloading any message data. If the provider is not
- * capable of this operation it should specifically set the body of the message to null
- * so that upper levels can detect that a full body download is needed.
- */
- STRUCTURE,
-
- /**
- * A sane portion of the entire message, cut off at a provider determined limit.
- * This should generaly be around 50kB.
- */
- BODY_SANE,
-
- /**
- * The entire message.
- */
- BODY,
- }
-}
diff --git a/src/com/android/email/mail/Flag.java b/src/com/android/email/mail/Flag.java
deleted file mode 100644
index 51f0096ff..000000000
--- a/src/com/android/email/mail/Flag.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-/**
- * Flags that can be applied to Messages.
- */
-public enum Flag {
- DELETED,
- SEEN,
- ANSWERED,
- FLAGGED,
- DRAFT,
- RECENT,
-
- /*
- * The following flags are for internal library use only.
- * TODO Eventually we should creates a Flags class that extends ArrayList that allows
- * these flags and Strings to represent user defined flags. At that point the below
- * flags should become user defined flags.
- */
- /**
- * Delete and remove from the LocalStore immediately.
- */
- X_DESTROYED,
-
- /**
- * Sending of an unsent message failed. It will be retried. Used to show status.
- */
- X_SEND_FAILED,
-
- /**
- * Sending of an unsent message is in progress.
- */
- X_SEND_IN_PROGRESS,
-
- /**
- * Indicates that a message is fully downloaded from the server and can be viewed normally.
- * This does not include attachments, which are never downloaded fully.
- */
- X_DOWNLOADED_FULL,
-
- /**
- * Indicates that a message is partially downloaded from the server and can be viewed but
- * more content is available on the server.
- * This does not include attachments, which are never downloaded fully.
- */
- X_DOWNLOADED_PARTIAL,
-}
diff --git a/src/com/android/email/mail/Folder.java b/src/com/android/email/mail/Folder.java
deleted file mode 100644
index f5ceb570e..000000000
--- a/src/com/android/email/mail/Folder.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-
-public abstract class Folder {
- public enum OpenMode {
- READ_WRITE, READ_ONLY,
- }
-
- public enum FolderType {
- HOLDS_FOLDERS, HOLDS_MESSAGES,
- }
-
- /**
- * Forces an open of the MailProvider. If the provider is already open this
- * function returns without doing anything.
- *
- * @param mode READ_ONLY or READ_WRITE
- */
- public abstract void open(OpenMode mode) throws MessagingException;
-
- /**
- * Forces a close of the MailProvider. Any further access will attempt to
- * reopen the MailProvider.
- *
- * @param expunge If true all deleted messages will be expunged.
- */
- public abstract void close(boolean expunge) throws MessagingException;
-
- /**
- * @return True if further commands are not expected to have to open the
- * connection.
- */
- // TODO not used, get rid of this - it's a transport function
- public abstract boolean isOpen();
-
- /**
- * Get the mode the folder was opened with. This may be different than the mode the open
- * was requested with.
- * @return
- */
- public abstract OpenMode getMode() throws MessagingException;
-
- public abstract boolean create(FolderType type) throws MessagingException;
-
- public abstract boolean exists() throws MessagingException;
-
- /**
- * @return A count of the messages in the selected folder.
- */
- public abstract int getMessageCount() throws MessagingException;
-
- public abstract int getUnreadMessageCount() throws MessagingException;
-
- public abstract Message getMessage(String uid) throws MessagingException;
-
- public abstract Message[] getMessages(int start, int end, MessageRetrievalListener listener)
- throws MessagingException;
-
- /**
- * Fetches the given list of messages. The specified listener is notified as
- * each fetch completes. Messages are downloaded as (as) lightweight (as
- * possible) objects to be filled in with later requests. In most cases this
- * means that only the UID is downloaded.
- *
- * @param uids
- * @param listener
- */
- public abstract Message[] getMessages(MessageRetrievalListener listener)
- throws MessagingException;
-
- public abstract Message[] getMessages(String[] uids, MessageRetrievalListener listener)
- throws MessagingException;
-
- public abstract void appendMessages(Message[] messages) throws MessagingException;
-
- public abstract void copyMessages(Message[] msgs, Folder folder) throws MessagingException;
-
- public abstract void setFlags(Message[] messages, Flag[] flags, boolean value)
- throws MessagingException;
-
- public abstract Message[] expunge() throws MessagingException;
-
- public abstract void fetch(Message[] messages, FetchProfile fp,
- MessageRetrievalListener listener) throws MessagingException;
-
- public abstract void delete(boolean recurse) throws MessagingException;
-
- public abstract String getName();
-
- public abstract Flag[] getPermanentFlags() throws MessagingException;
-
- @Override
- public String toString() {
- return getName();
- }
-}
diff --git a/src/com/android/email/mail/Message.java b/src/com/android/email/mail/Message.java
deleted file mode 100644
index 2f4b812a2..000000000
--- a/src/com/android/email/mail/Message.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-import java.util.Date;
-import java.util.HashSet;
-
-public abstract class Message implements Part, Body {
- public enum RecipientType {
- TO, CC, BCC,
- }
-
- protected String mUid;
-
- protected HashSet<Flag> mFlags = new HashSet<Flag>();
-
- protected Date mInternalDate;
-
- protected Folder mFolder;
-
- public String getUid() {
- return mUid;
- }
-
- public void setUid(String uid) {
- this.mUid = uid;
- }
-
- public Folder getFolder() {
- return mFolder;
- }
-
- public abstract String getSubject() throws MessagingException;
-
- public abstract void setSubject(String subject) throws MessagingException;
-
- public Date getInternalDate() {
- return mInternalDate;
- }
-
- public void setInternalDate(Date internalDate) {
- this.mInternalDate = internalDate;
- }
-
- public abstract Date getReceivedDate() throws MessagingException;
-
- public abstract Date getSentDate() throws MessagingException;
-
- public abstract void setSentDate(Date sentDate) throws MessagingException;
-
- public abstract Address[] getRecipients(RecipientType type) throws MessagingException;
-
- public abstract void setRecipients(RecipientType type, Address[] addresses)
- throws MessagingException;
-
- public void setRecipient(RecipientType type, Address address) throws MessagingException {
- setRecipients(type, new Address[] {
- address
- });
- }
-
- public abstract Address[] getFrom() throws MessagingException;
-
- public abstract void setFrom(Address from) throws MessagingException;
-
- public abstract Address[] getReplyTo() throws MessagingException;
-
- public abstract void setReplyTo(Address[] from) throws MessagingException;
-
- public abstract Body getBody() throws MessagingException;
-
- public abstract String getContentType() throws MessagingException;
-
- public abstract void addHeader(String name, String value) throws MessagingException;
-
- public abstract void setHeader(String name, String value) throws MessagingException;
-
- public abstract String[] getHeader(String name) throws MessagingException;
-
- public abstract void removeHeader(String name) throws MessagingException;
-
- public abstract void setBody(Body body) throws MessagingException;
-
- public boolean isMimeType(String mimeType) throws MessagingException {
- return getContentType().startsWith(mimeType);
- }
-
- /*
- * TODO Refactor Flags at some point to be able to store user defined flags.
- */
- public Flag[] getFlags() {
- return mFlags.toArray(new Flag[] {});
- }
-
- public void setFlag(Flag flag, boolean set) throws MessagingException {
- if (set) {
- mFlags.add(flag);
- } else {
- mFlags.remove(flag);
- }
- }
-
- /**
- * This method calls setFlag(Flag, boolean)
- * @param flags
- * @param set
- */
- public void setFlags(Flag[] flags, boolean set) throws MessagingException {
- for (Flag flag : flags) {
- setFlag(flag, set);
- }
- }
-
- public boolean isSet(Flag flag) {
- return mFlags.contains(flag);
- }
-
- public abstract void saveChanges() throws MessagingException;
-}
diff --git a/src/com/android/email/mail/MessageDateComparator.java b/src/com/android/email/mail/MessageDateComparator.java
deleted file mode 100644
index df7d93bb6..000000000
--- a/src/com/android/email/mail/MessageDateComparator.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-import java.util.Comparator;
-
-public class MessageDateComparator implements Comparator<Message> {
- public int compare(Message o1, Message o2) {
- try {
- if (o1.getSentDate() == null) {
- return 1;
- } else if (o2.getSentDate() == null) {
- return -1;
- } else
- return o2.getSentDate().compareTo(o1.getSentDate());
- } catch (Exception e) {
- return 0;
- }
- }
-}
diff --git a/src/com/android/email/mail/MessageRetrievalListener.java b/src/com/android/email/mail/MessageRetrievalListener.java
deleted file mode 100644
index 26f20d09a..000000000
--- a/src/com/android/email/mail/MessageRetrievalListener.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-public interface MessageRetrievalListener {
- public void messageStarted(String uid, int number, int ofTotal);
-
- public void messageFinished(Message message, int number, int ofTotal);
-}
diff --git a/src/com/android/email/mail/MessagingException.java b/src/com/android/email/mail/MessagingException.java
deleted file mode 100644
index 2a11cece0..000000000
--- a/src/com/android/email/mail/MessagingException.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-/**
- * This exception is used for most types of failures that occur during server interactions.
- *
- * Data passed through this exception should be considered non-localized. Any strings should
- * either be internal-only (for debugging) or server-generated.
- *
- * TO DO: Does it make sense to further collapse AuthenticationFailedException and
- * CertificateValidationException and any others into this?
- */
-public class MessagingException extends Exception {
- public static final long serialVersionUID = -1;
-
- /** Any exception that does not specify a specific issue */
- public static final int UNSPECIFIED_EXCEPTION = 0;
- /** Connection or IO errors */
- public static final int IOERROR = 1;
- /** The configuration requested TLS but the server did not support it. */
- public static final int TLS_REQUIRED = 2;
- /** Authentication is required but the server did not support it. */
- public static final int AUTH_REQUIRED = 3;
- /** General security failures */
- public static final int GENERAL_SECURITY = 4;
-
- private final int mExceptionType;
-
-
- public MessagingException(String message) {
- super(message);
- mExceptionType = UNSPECIFIED_EXCEPTION;
- }
-
- public MessagingException(String message, Throwable throwable) {
- super(message, throwable);
- mExceptionType = UNSPECIFIED_EXCEPTION;
- }
-
- /**
- * Constructs a MessagingException with an exceptionType and a null message.
- * @param exceptionType The exception type to set for this exception.
- */
- public MessagingException(int exceptionType) {
- super();
- mExceptionType = exceptionType;
- }
-
- /**
- * Constructs a MessagingException with an exceptionType and a message.
- * @param exceptionType The exception type to set for this exception.
- */
- public MessagingException(int exceptionType, String message) {
- super(message);
- mExceptionType = exceptionType;
- }
-
- /**
- * Return the exception type. Will be OTHER_EXCEPTION if not explicitly set.
- *
- * @return Returns the exception type.
- */
- public int getExceptionType() {
- return mExceptionType;
- }
-}
diff --git a/src/com/android/email/mail/Multipart.java b/src/com/android/email/mail/Multipart.java
deleted file mode 100644
index fa9a2c88d..000000000
--- a/src/com/android/email/mail/Multipart.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-import java.util.ArrayList;
-
-public abstract class Multipart implements Body {
- protected Part mParent;
-
- protected ArrayList<BodyPart> mParts = new ArrayList<BodyPart>();
-
- protected String mContentType;
-
- public void addBodyPart(BodyPart part) throws MessagingException {
- mParts.add(part);
- }
-
- public void addBodyPart(BodyPart part, int index) throws MessagingException {
- mParts.add(index, part);
- }
-
- public BodyPart getBodyPart(int index) throws MessagingException {
- return mParts.get(index);
- }
-
- public String getContentType() throws MessagingException {
- return mContentType;
- }
-
- public int getCount() throws MessagingException {
- return mParts.size();
- }
-
- public boolean removeBodyPart(BodyPart part) throws MessagingException {
- return mParts.remove(part);
- }
-
- public void removeBodyPart(int index) throws MessagingException {
- mParts.remove(index);
- }
-
- public Part getParent() throws MessagingException {
- return mParent;
- }
-
- public void setParent(Part parent) throws MessagingException {
- this.mParent = parent;
- }
-}
diff --git a/src/com/android/email/mail/NoSuchProviderException.java b/src/com/android/email/mail/NoSuchProviderException.java
deleted file mode 100644
index a857f40c2..000000000
--- a/src/com/android/email/mail/NoSuchProviderException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-public class NoSuchProviderException extends MessagingException {
- public static final long serialVersionUID = -1;
-
- public NoSuchProviderException(String message) {
- super(message);
- }
-
- public NoSuchProviderException(String message, Throwable throwable) {
- super(message, throwable);
- }
-}
diff --git a/src/com/android/email/mail/Part.java b/src/com/android/email/mail/Part.java
deleted file mode 100644
index 1e1fcf498..000000000
--- a/src/com/android/email/mail/Part.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public interface Part {
- public void addHeader(String name, String value) throws MessagingException;
-
- public void removeHeader(String name) throws MessagingException;
-
- public void setHeader(String name, String value) throws MessagingException;
-
- public Body getBody() throws MessagingException;
-
- public String getContentType() throws MessagingException;
-
- public String getDisposition() throws MessagingException;
-
- public String[] getHeader(String name) throws MessagingException;
-
- public int getSize() throws MessagingException;
-
- public boolean isMimeType(String mimeType) throws MessagingException;
-
- public String getMimeType() throws MessagingException;
-
- public void setBody(Body body) throws MessagingException;
-
- public void writeTo(OutputStream out) throws IOException, MessagingException;
-}
diff --git a/src/com/android/email/mail/Sender.java b/src/com/android/email/mail/Sender.java
deleted file mode 100644
index e89bd9a95..000000000
--- a/src/com/android/email/mail/Sender.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-import com.android.email.mail.transport.SmtpSender;
-
-public abstract class Sender {
- protected static final int SOCKET_CONNECT_TIMEOUT = 10000;
-
- public synchronized static Sender getInstance(String uri) throws MessagingException {
- if (uri.startsWith("smtp")) {
- return new SmtpSender(uri);
- } else {
- throw new MessagingException("Unable to locate an applicable Transport for " + uri);
- }
- }
-
- public abstract void open() throws MessagingException;
-
- public abstract void sendMessage(Message message) throws MessagingException;
-
- public abstract void close() throws MessagingException;
-}
diff --git a/src/com/android/email/mail/Store.java b/src/com/android/email/mail/Store.java
deleted file mode 100644
index 8c6f7c419..000000000
--- a/src/com/android/email/mail/Store.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-import java.util.HashMap;
-
-import android.app.Application;
-
-import com.android.email.mail.store.ImapStore;
-import com.android.email.mail.store.LocalStore;
-import com.android.email.mail.store.Pop3Store;
-
-/**
- * Store is the access point for an email message store. It's location can be
- * local or remote and no specific protocol is defined. Store is intended to
- * loosely model in combination the JavaMail classes javax.mail.Store and
- * javax.mail.Folder along with some additional functionality to improve
- * performance on mobile devices. Implementations of this class should focus on
- * making as few network connections as possible.
- */
-public abstract class Store {
-
- /**
- * String constants for known store schemes.
- */
- public static final String STORE_SCHEME_IMAP = "imap";
- public static final String STORE_SCHEME_POP3 = "pop3";
- public static final String STORE_SCHEME_LOCAL = "local";
-
- /**
- * A global suggestion to Store implementors on how much of the body
- * should be returned on FetchProfile.Item.BODY_SANE requests.
- */
- public static final int FETCH_BODY_SANE_SUGGESTED_SIZE = (50 * 1024);
-
- private static HashMap<String, Store> mStores = new HashMap<String, Store>();
-
- /**
- * Get an instance of a mail store. The URI is parsed as a standard URI and
- * the scheme is used to determine which protocol will be used. The
- * following schemes are currently recognized: imap - IMAP with no
- * connection security. Ex: imap://username:password@host/ imap+tls - IMAP
- * with TLS connection security, if the server supports it. Ex:
- * imap+tls://username:password@host imap+tls+ - IMAP with required TLS
- * connection security. Connection fails if TLS is not available. Ex:
- * imap+tls+://username:password@host imap+ssl+ - IMAP with required SSL
- * connection security. Connection fails if SSL is not available. Ex:
- * imap+ssl+://username:password@host
- *
- * @param uri The URI of the store.
- * @return an initialized store of the appropriate class
- * @throws MessagingException
- */
- public synchronized static Store getInstance(String uri, Application application) throws MessagingException {
- Store store = mStores.get(uri);
- if (store == null) {
- if (uri.startsWith(STORE_SCHEME_IMAP)) {
- store = new ImapStore(uri);
- } else if (uri.startsWith(STORE_SCHEME_POP3)) {
- store = new Pop3Store(uri);
- } else if (uri.startsWith(STORE_SCHEME_LOCAL)) {
- store = new LocalStore(uri, application);
- }
-
- if (store != null) {
- mStores.put(uri, store);
- }
- }
-
- if (store == null) {
- throw new MessagingException("Unable to locate an applicable Store for " + uri);
- }
-
- return store;
- }
-
- public abstract Folder getFolder(String name) throws MessagingException;
-
- public abstract Folder[] getPersonalNamespaces() throws MessagingException;
-
- public abstract void checkSettings() throws MessagingException;
-}
diff --git a/src/com/android/email/mail/Transport.java b/src/com/android/email/mail/Transport.java
deleted file mode 100644
index 4013d9194..000000000
--- a/src/com/android/email/mail/Transport.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.SocketException;
-import java.net.URI;
-
-/**
- * This interface defines a "transport", which is defined here as being one layer below the
- * specific wire protocols such as POP3, IMAP, or SMTP.
- *
- * Practically speaking, it provides a definition of the common functionality between them
- * (dealing with sockets & streams, SSL, logging, and so forth), and provides a seam just below
- * the individual protocols to enable better testing.
- *
- * The following features are supported and presumed to be common:
- *
- * Interpretation of URI
- * Support for SSL and TLS wireline security
- */
-public interface Transport {
-
- /**
- * Connection security options for transport that supports SSL and/or TLS
- */
- public static final int CONNECTION_SECURITY_NONE = 0;
- public static final int CONNECTION_SECURITY_TLS_OPTIONAL = 1;
- public static final int CONNECTION_SECURITY_TLS_REQUIRED = 2;
- public static final int CONNECTION_SECURITY_SSL_REQUIRED = 3;
- public static final int CONNECTION_SECURITY_SSL_OPTIONAL = 4;
-
- /**
- * Get a new transport, using an existing one as a model. The new transport is configured as if
- * setUri() and setSecurity() have been called, but not opened or connected in any way.
- * @return a new Transport ready to open()
- */
- public Transport newInstanceWithConfiguration();
-
- /**
- * Set the Uri for the connection.
- *
- * @param uri The Uri for the connection
- * @param defaultPort If the Uri does not include an explicit port, this value will be used.
- */
- public void setUri(URI uri, int defaultPort);
-
- /**
- * @return Returns the host part of the Uri
- */
- public String getHost();
-
- /**
- * @return Returns the port (either from the Uri or from the default)
- */
- public int getPort();
-
- /**
- * Returns the user info parts of the Uri, if any were supplied. Typically, [0] is the user
- * and [1] is the password.
- * @return Returns the user info parts of the Uri. Null if none were supplied.
- */
- public String[] getUserInfoParts();
-
- /**
- * Set the desired security mode for this connection.
- * @param connectionSecurity A value indicating the desired security mode.
- */
- public void setSecurity(int connectionSecurity);
-
- /**
- * @return Returns the desired security mode for this connection.
- */
- public int getSecurity();
-
- /**
- * @return true if the security mode indicates that SSL is possible (optional or required)
- */
- public boolean canTrySslSecurity();
-
- /**
- * @return true if the security mode indicates that TLS is possible (optional or required)
- */
- public boolean canTryTlsSecurity();
-
- /**
- * Set the socket timeout.
- * @param timeoutMilliseconds the read timeout value if greater than {@code 0}, or
- * {@code 0} for an infinite timeout.
- */
- public void setSoTimeout(int timeoutMilliseconds) throws SocketException;
-
- /**
- * Attempts to open the connection using the supplied parameters, and using SSL if indicated.
- */
- public void open() throws MessagingException, CertificateValidationException;
-
- /**
- * Attempts to reopen the connection using TLS.
- */
- public void reopenTls() throws MessagingException;
-
- /**
- * @return true if the connection is open
- */
- public boolean isOpen();
-
- /**
- * Closes the connection. Does not send any closure messages, simply closes the socket and the
- * associated streams. Best effort only. Catches all exceptions and always returns.
- *
- * MUST NOT throw any exceptions.
- */
- public void close();
-
- /**
- * @return returns the active input stream
- */
- public InputStream getInputStream();
-
- /**
- * @return returns the active output stream
- */
- public OutputStream getOutputStream();
-
- /**
- * Write a single line to the server, and may generate a log entry (if enabled).
- * @param s The text to send to the server.
- * @param sensitiveReplacement If the command includes sensitive data (e.g. authentication)
- * please pass a replacement string here (for logging). Most callers simply pass null,
- */
- void writeLine(String s, String sensitiveReplacement) throws IOException;
-
- /**
- * Reads a single line from the server. Any delimiter characters will not be included in the
- * result. May generate a log entry, if enabled.
- * @return Returns the string from the server.
- * @throws IOException
- */
- String readLine() throws IOException;
-
-}
diff --git a/src/com/android/email/mail/internet/BinaryTempFileBody.java b/src/com/android/email/mail/internet/BinaryTempFileBody.java
deleted file mode 100644
index 180011129..000000000
--- a/src/com/android/email/mail/internet/BinaryTempFileBody.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.internet;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.apache.commons.io.IOUtils;
-
-import android.util.Config;
-import android.util.Log;
-
-import com.android.email.Email;
-import com.android.email.codec.binary.Base64OutputStream;
-import com.android.email.mail.Body;
-import com.android.email.mail.MessagingException;
-
-/**
- * A Body that is backed by a temp file. The Body exposes a getOutputStream method that allows
- * the user to write to the temp file. After the write the body is available via getInputStream
- * and writeTo one time. After writeTo is called, or the InputStream returned from
- * getInputStream is closed the file is deleted and the Body should be considered disposed of.
- */
-public class BinaryTempFileBody implements Body {
- private static File mTempDirectory;
-
- private File mFile;
-
- public static void setTempDirectory(File tempDirectory) {
- mTempDirectory = tempDirectory;
- }
-
- public BinaryTempFileBody() throws IOException {
- if (mTempDirectory == null) {
- throw new
- RuntimeException("setTempDirectory has not been called on BinaryTempFileBody!");
- }
- }
-
- public OutputStream getOutputStream() throws IOException {
- mFile = File.createTempFile("body", null, mTempDirectory);
- mFile.deleteOnExit();
- return new FileOutputStream(mFile);
- }
-
- public InputStream getInputStream() throws MessagingException {
- try {
- return new BinaryTempFileBodyInputStream(new FileInputStream(mFile));
- }
- catch (IOException ioe) {
- throw new MessagingException("Unable to open body", ioe);
- }
- }
-
- public void writeTo(OutputStream out) throws IOException, MessagingException {
- InputStream in = getInputStream();
- Base64OutputStream base64Out = new Base64OutputStream(out);
- IOUtils.copy(in, base64Out);
- base64Out.close();
- mFile.delete();
- }
-
- class BinaryTempFileBodyInputStream extends FilterInputStream {
- public BinaryTempFileBodyInputStream(InputStream in) {
- super(in);
- }
-
- @Override
- public void close() throws IOException {
- super.close();
- mFile.delete();
- }
- }
-}
diff --git a/src/com/android/email/mail/internet/MimeBodyPart.java b/src/com/android/email/mail/internet/MimeBodyPart.java
deleted file mode 100644
index f105a3110..000000000
--- a/src/com/android/email/mail/internet/MimeBodyPart.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.internet;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-
-import com.android.email.mail.Body;
-import com.android.email.mail.BodyPart;
-import com.android.email.mail.MessagingException;
-
-/**
- * TODO this is a close approximation of Message, need to update along with
- * Message.
- */
-public class MimeBodyPart extends BodyPart {
- protected MimeHeader mHeader = new MimeHeader();
- protected Body mBody;
- protected int mSize;
-
- public MimeBodyPart() throws MessagingException {
- this(null);
- }
-
- public MimeBodyPart(Body body) throws MessagingException {
- this(body, null);
- }
-
- public MimeBodyPart(Body body, String mimeType) throws MessagingException {
- if (mimeType != null) {
- setHeader(MimeHeader.HEADER_CONTENT_TYPE, mimeType);
- }
- setBody(body);
- }
-
- protected String getFirstHeader(String name) throws MessagingException {
- return mHeader.getFirstHeader(name);
- }
-
- public void addHeader(String name, String value) throws MessagingException {
- mHeader.addHeader(name, value);
- }
-
- public void setHeader(String name, String value) throws MessagingException {
- mHeader.setHeader(name, value);
- }
-
- public String[] getHeader(String name) throws MessagingException {
- return mHeader.getHeader(name);
- }
-
- public void removeHeader(String name) throws MessagingException {
- mHeader.removeHeader(name);
- }
-
- public Body getBody() throws MessagingException {
- return mBody;
- }
-
- public void setBody(Body body) throws MessagingException {
- this.mBody = body;
- if (body instanceof com.android.email.mail.Multipart) {
- com.android.email.mail.Multipart multipart = ((com.android.email.mail.Multipart)body);
- multipart.setParent(this);
- setHeader(MimeHeader.HEADER_CONTENT_TYPE, multipart.getContentType());
- }
- else if (body instanceof TextBody) {
- String contentType = String.format("%s;\n charset=utf-8", getMimeType());
- String name = MimeUtility.getHeaderParameter(getContentType(), "name");
- if (name != null) {
- contentType += String.format(";\n name=\"%s\"", name);
- }
- setHeader(MimeHeader.HEADER_CONTENT_TYPE, contentType);
- setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64");
- }
- }
-
- public String getContentType() throws MessagingException {
- String contentType = getFirstHeader(MimeHeader.HEADER_CONTENT_TYPE);
- if (contentType == null) {
- return "text/plain";
- } else {
- return contentType;
- }
- }
-
- public String getDisposition() throws MessagingException {
- String contentDisposition = getFirstHeader(MimeHeader.HEADER_CONTENT_DISPOSITION);
- if (contentDisposition == null) {
- return null;
- } else {
- return contentDisposition;
- }
- }
-
- public String getMimeType() throws MessagingException {
- return MimeUtility.getHeaderParameter(getContentType(), null);
- }
-
- public boolean isMimeType(String mimeType) throws MessagingException {
- return getMimeType().equals(mimeType);
- }
-
- public int getSize() throws MessagingException {
- return mSize;
- }
-
- /**
- * Write the MimeMessage out in MIME format.
- */
- public void writeTo(OutputStream out) throws IOException, MessagingException {
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
- mHeader.writeTo(out);
- writer.write("\r\n");
- writer.flush();
- if (mBody != null) {
- mBody.writeTo(out);
- }
- }
-}
diff --git a/src/com/android/email/mail/internet/MimeHeader.java b/src/com/android/email/mail/internet/MimeHeader.java
deleted file mode 100644
index 89a7c7412..000000000
--- a/src/com/android/email/mail/internet/MimeHeader.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.internet;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.util.ArrayList;
-
-import com.android.email.Utility;
-import com.android.email.mail.MessagingException;
-
-public class MimeHeader {
- /**
- * Application specific header that contains Store specific information about an attachment.
- * In IMAP this contains the IMAP BODYSTRUCTURE part id so that the ImapStore can later
- * retrieve the attachment at will from the server.
- * The info is recorded from this header on LocalStore.appendMessages and is put back
- * into the MIME data by LocalStore.fetch.
- */
- public static final String HEADER_ANDROID_ATTACHMENT_STORE_DATA = "X-Android-Attachment-StoreData";
-
- public static final String HEADER_CONTENT_TYPE = "Content-Type";
- public static final String HEADER_CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
- public static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition";
-
- /**
- * Fields that should be omitted when writing the header using writeTo()
- */
- private static final String[] writeOmitFields = {
-// HEADER_ANDROID_ATTACHMENT_DOWNLOADED,
-// HEADER_ANDROID_ATTACHMENT_ID,
- HEADER_ANDROID_ATTACHMENT_STORE_DATA
- };
-
- protected ArrayList<Field> mFields = new ArrayList<Field>();
-
- public void clear() {
- mFields.clear();
- }
-
- public String getFirstHeader(String name) throws MessagingException {
- String[] header = getHeader(name);
- if (header == null) {
- return null;
- }
- return header[0];
- }
-
- public void addHeader(String name, String value) throws MessagingException {
- mFields.add(new Field(name, MimeUtility.foldAndEncode(value)));
- }
-
- public void setHeader(String name, String value) throws MessagingException {
- if (name == null || value == null) {
- return;
- }
- removeHeader(name);
- addHeader(name, value);
- }
-
- public String[] getHeader(String name) throws MessagingException {
- ArrayList<String> values = new ArrayList<String>();
- for (Field field : mFields) {
- if (field.name.equalsIgnoreCase(name)) {
- values.add(field.value);
- }
- }
- if (values.size() == 0) {
- return null;
- }
- return values.toArray(new String[] {});
- }
-
- public void removeHeader(String name) throws MessagingException {
- ArrayList<Field> removeFields = new ArrayList<Field>();
- for (Field field : mFields) {
- if (field.name.equalsIgnoreCase(name)) {
- removeFields.add(field);
- }
- }
- mFields.removeAll(removeFields);
- }
-
- public void writeTo(OutputStream out) throws IOException, MessagingException {
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
- for (Field field : mFields) {
- if (!Utility.arrayContains(writeOmitFields, field.name)) {
- writer.write(field.name + ": " + field.value + "\r\n");
- }
- }
- writer.flush();
- }
-
- class Field {
- String name;
-
- String value;
-
- public Field(String name, String value) {
- this.name = name;
- this.value = value;
- }
- }
-}
diff --git a/src/com/android/email/mail/internet/MimeMessage.java b/src/com/android/email/mail/internet/MimeMessage.java
deleted file mode 100644
index 6a2339d59..000000000
--- a/src/com/android/email/mail/internet/MimeMessage.java
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.internet;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.Stack;
-
-import org.apache.james.mime4j.BodyDescriptor;
-import org.apache.james.mime4j.ContentHandler;
-import org.apache.james.mime4j.EOLConvertingInputStream;
-import org.apache.james.mime4j.MimeStreamParser;
-import org.apache.james.mime4j.field.DateTimeField;
-import org.apache.james.mime4j.field.Field;
-
-import com.android.email.mail.Address;
-import com.android.email.mail.Body;
-import com.android.email.mail.BodyPart;
-import com.android.email.mail.Message;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Part;
-
-/**
- * An implementation of Message that stores all of it's metadata in RFC 822 and
- * RFC 2045 style headers.
- */
-public class MimeMessage extends Message {
- protected MimeHeader mHeader = new MimeHeader();
- protected Address[] mFrom;
- protected Address[] mTo;
- protected Address[] mCc;
- protected Address[] mBcc;
- protected Address[] mReplyTo;
- protected Date mSentDate;
- // In MIME, en_US-like date format should be used. In other words "MMM" should be encoded to
- // "Jan", not the other localized format like "Ene" (meaning January in locale es).
- // This conversion is used when generating outgoing MIME messages. Incoming MIME date
- // headers are parsed by org.apache.james.mime4j.field.DateTimeField which does not have any
- // localization code.
- protected SimpleDateFormat mDateFormat =
- new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
- protected Body mBody;
- protected int mSize;
-
- public MimeMessage() {
- /*
- * Every new messages gets a Message-ID
- */
- try {
- setHeader("Message-ID", generateMessageId());
- }
- catch (MessagingException me) {
- throw new RuntimeException("Unable to create MimeMessage", me);
- }
- }
-
- private String generateMessageId() {
- StringBuffer sb = new StringBuffer();
- sb.append("<");
- for (int i = 0; i < 24; i++) {
- sb.append(Integer.toString((int)(Math.random() * 35), 36));
- }
- sb.append(".");
- sb.append(Long.toString(System.currentTimeMillis()));
- sb.append("@email.android.com>");
- return sb.toString();
- }
-
- /**
- * Parse the given InputStream using Apache Mime4J to build a MimeMessage.
- *
- * @param in
- * @throws IOException
- * @throws MessagingException
- */
- public MimeMessage(InputStream in) throws IOException, MessagingException {
- parse(in);
- }
-
- protected void parse(InputStream in) throws IOException, MessagingException {
- mHeader.clear();
- mBody = null;
- mBcc = null;
- mTo = null;
- mFrom = null;
- mSentDate = null;
-
- MimeStreamParser parser = new MimeStreamParser();
- parser.setContentHandler(new MimeMessageBuilder());
- parser.parse(new EOLConvertingInputStream(in));
- }
-
- public Date getReceivedDate() throws MessagingException {
- return null;
- }
-
- public Date getSentDate() throws MessagingException {
- if (mSentDate == null) {
- try {
- DateTimeField field = (DateTimeField)Field.parse("Date: "
- + MimeUtility.unfoldAndDecode(getFirstHeader("Date")));
- mSentDate = field.getDate();
- } catch (Exception e) {
-
- }
- }
- return mSentDate;
- }
-
- public void setSentDate(Date sentDate) throws MessagingException {
- setHeader("Date", mDateFormat.format(sentDate));
- this.mSentDate = sentDate;
- }
-
- public String getContentType() throws MessagingException {
- String contentType = getFirstHeader(MimeHeader.HEADER_CONTENT_TYPE);
- if (contentType == null) {
- return "text/plain";
- } else {
- return contentType;
- }
- }
-
- public String getDisposition() throws MessagingException {
- String contentDisposition = getFirstHeader(MimeHeader.HEADER_CONTENT_DISPOSITION);
- if (contentDisposition == null) {
- return null;
- } else {
- return contentDisposition;
- }
- }
-
- public String getMimeType() throws MessagingException {
- return MimeUtility.getHeaderParameter(getContentType(), null);
- }
-
- public int getSize() throws MessagingException {
- return mSize;
- }
-
- /**
- * Returns a list of the given recipient type from this message. If no addresses are
- * found the method returns an empty array.
- */
- public Address[] getRecipients(RecipientType type) throws MessagingException {
- if (type == RecipientType.TO) {
- if (mTo == null) {
- mTo = Address.parse(MimeUtility.unfold(getFirstHeader("To")));
- }
- return mTo;
- } else if (type == RecipientType.CC) {
- if (mCc == null) {
- mCc = Address.parse(MimeUtility.unfold(getFirstHeader("CC")));
- }
- return mCc;
- } else if (type == RecipientType.BCC) {
- if (mBcc == null) {
- mBcc = Address.parse(MimeUtility.unfold(getFirstHeader("BCC")));
- }
- return mBcc;
- } else {
- throw new MessagingException("Unrecognized recipient type.");
- }
- }
-
- public void setRecipients(RecipientType type, Address[] addresses) throws MessagingException {
- if (type == RecipientType.TO) {
- if (addresses == null || addresses.length == 0) {
- removeHeader("To");
- this.mTo = null;
- } else {
- setHeader("To", Address.toString(addresses));
- this.mTo = addresses;
- }
- } else if (type == RecipientType.CC) {
- if (addresses == null || addresses.length == 0) {
- removeHeader("CC");
- this.mCc = null;
- } else {
- setHeader("CC", Address.toString(addresses));
- this.mCc = addresses;
- }
- } else if (type == RecipientType.BCC) {
- if (addresses == null || addresses.length == 0) {
- removeHeader("BCC");
- this.mBcc = null;
- } else {
- setHeader("BCC", Address.toString(addresses));
- this.mBcc = addresses;
- }
- } else {
- throw new MessagingException("Unrecognized recipient type.");
- }
- }
-
- /**
- * Returns the unfolded, decoded value of the Subject header.
- */
- public String getSubject() throws MessagingException {
- return MimeUtility.unfoldAndDecode(getFirstHeader("Subject"));
- }
-
- public void setSubject(String subject) throws MessagingException {
- setHeader("Subject", subject);
- }
-
- public Address[] getFrom() throws MessagingException {
- if (mFrom == null) {
- String list = MimeUtility.unfold(getFirstHeader("From"));
- if (list == null || list.length() == 0) {
- list = MimeUtility.unfold(getFirstHeader("Sender"));
- }
- mFrom = Address.parse(list);
- }
- return mFrom;
- }
-
- public void setFrom(Address from) throws MessagingException {
- if (from != null) {
- setHeader("From", from.toString());
- this.mFrom = new Address[] {
- from
- };
- } else {
- this.mFrom = null;
- }
- }
-
- public Address[] getReplyTo() throws MessagingException {
- if (mReplyTo == null) {
- mReplyTo = Address.parse(MimeUtility.unfold(getFirstHeader("Reply-to")));
- }
- return mReplyTo;
- }
-
- public void setReplyTo(Address[] replyTo) throws MessagingException {
- if (replyTo == null || replyTo.length == 0) {
- removeHeader("Reply-to");
- mReplyTo = null;
- } else {
- setHeader("Reply-to", Address.toString(replyTo));
- mReplyTo = replyTo;
- }
- }
-
- public void saveChanges() throws MessagingException {
- throw new MessagingException("saveChanges not yet implemented");
- }
-
- public Body getBody() throws MessagingException {
- return mBody;
- }
-
- public void setBody(Body body) throws MessagingException {
- this.mBody = body;
- if (body instanceof com.android.email.mail.Multipart) {
- com.android.email.mail.Multipart multipart = ((com.android.email.mail.Multipart)body);
- multipart.setParent(this);
- setHeader(MimeHeader.HEADER_CONTENT_TYPE, multipart.getContentType());
- setHeader("MIME-Version", "1.0");
- }
- else if (body instanceof TextBody) {
- setHeader(MimeHeader.HEADER_CONTENT_TYPE, String.format("%s;\n charset=utf-8",
- getMimeType()));
- setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64");
- }
- }
-
- protected String getFirstHeader(String name) throws MessagingException {
- return mHeader.getFirstHeader(name);
- }
-
- public void addHeader(String name, String value) throws MessagingException {
- mHeader.addHeader(name, value);
- }
-
- public void setHeader(String name, String value) throws MessagingException {
- mHeader.setHeader(name, value);
- }
-
- public String[] getHeader(String name) throws MessagingException {
- return mHeader.getHeader(name);
- }
-
- public void removeHeader(String name) throws MessagingException {
- mHeader.removeHeader(name);
- }
-
- public void writeTo(OutputStream out) throws IOException, MessagingException {
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
- mHeader.writeTo(out);
- writer.write("\r\n");
- writer.flush();
- if (mBody != null) {
- mBody.writeTo(out);
- }
- }
-
- public InputStream getInputStream() throws MessagingException {
- return null;
- }
-
- class MimeMessageBuilder implements ContentHandler {
- private Stack stack = new Stack();
-
- public MimeMessageBuilder() {
- }
-
- private void expect(Class c) {
- if (!c.isInstance(stack.peek())) {
- throw new IllegalStateException("Internal stack error: " + "Expected '"
- + c.getName() + "' found '" + stack.peek().getClass().getName() + "'");
- }
- }
-
- public void startMessage() {
- if (stack.isEmpty()) {
- stack.push(MimeMessage.this);
- } else {
- expect(Part.class);
- try {
- MimeMessage m = new MimeMessage();
- ((Part)stack.peek()).setBody(m);
- stack.push(m);
- } catch (MessagingException me) {
- throw new Error(me);
- }
- }
- }
-
- public void endMessage() {
- expect(MimeMessage.class);
- stack.pop();
- }
-
- public void startHeader() {
- expect(Part.class);
- }
-
- public void field(String fieldData) {
- expect(Part.class);
- try {
- String[] tokens = fieldData.split(":", 2);
- ((Part)stack.peek()).addHeader(tokens[0], tokens[1].trim());
- } catch (MessagingException me) {
- throw new Error(me);
- }
- }
-
- public void endHeader() {
- expect(Part.class);
- }
-
- public void startMultipart(BodyDescriptor bd) {
- expect(Part.class);
-
- Part e = (Part)stack.peek();
- try {
- MimeMultipart multiPart = new MimeMultipart(e.getContentType());
- e.setBody(multiPart);
- stack.push(multiPart);
- } catch (MessagingException me) {
- throw new Error(me);
- }
- }
-
- public void body(BodyDescriptor bd, InputStream in) throws IOException {
- expect(Part.class);
- Body body = MimeUtility.decodeBody(in, bd.getTransferEncoding());
- try {
- ((Part)stack.peek()).setBody(body);
- } catch (MessagingException me) {
- throw new Error(me);
- }
- }
-
- public void endMultipart() {
- stack.pop();
- }
-
- public void startBodyPart() {
- expect(MimeMultipart.class);
-
- try {
- MimeBodyPart bodyPart = new MimeBodyPart();
- ((MimeMultipart)stack.peek()).addBodyPart(bodyPart);
- stack.push(bodyPart);
- } catch (MessagingException me) {
- throw new Error(me);
- }
- }
-
- public void endBodyPart() {
- expect(BodyPart.class);
- stack.pop();
- }
-
- public void epilogue(InputStream is) throws IOException {
- expect(MimeMultipart.class);
- StringBuffer sb = new StringBuffer();
- int b;
- while ((b = is.read()) != -1) {
- sb.append((char)b);
- }
- // ((Multipart) stack.peek()).setEpilogue(sb.toString());
- }
-
- public void preamble(InputStream is) throws IOException {
- expect(MimeMultipart.class);
- StringBuffer sb = new StringBuffer();
- int b;
- while ((b = is.read()) != -1) {
- sb.append((char)b);
- }
- try {
- ((MimeMultipart)stack.peek()).setPreamble(sb.toString());
- } catch (MessagingException me) {
- throw new Error(me);
- }
- }
-
- public void raw(InputStream is) throws IOException {
- throw new UnsupportedOperationException("Not supported");
- }
- }
-}
diff --git a/src/com/android/email/mail/internet/MimeMultipart.java b/src/com/android/email/mail/internet/MimeMultipart.java
deleted file mode 100644
index b0a2ddc71..000000000
--- a/src/com/android/email/mail/internet/MimeMultipart.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.internet;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-
-import com.android.email.mail.BodyPart;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Multipart;
-
-public class MimeMultipart extends Multipart {
- protected String mPreamble;
-
- protected String mContentType;
-
- protected String mBoundary;
-
- protected String mSubType;
-
- public MimeMultipart() throws MessagingException {
- mBoundary = generateBoundary();
- setSubType("mixed");
- }
-
- public MimeMultipart(String contentType) throws MessagingException {
- this.mContentType = contentType;
- try {
- mSubType = MimeUtility.getHeaderParameter(contentType, null).split("/")[1];
- mBoundary = MimeUtility.getHeaderParameter(contentType, "boundary");
- if (mBoundary == null) {
- throw new MessagingException("MultiPart does not contain boundary: " + contentType);
- }
- } catch (Exception e) {
- throw new MessagingException(
- "Invalid MultiPart Content-Type; must contain subtype and boundary. ("
- + contentType + ")", e);
- }
- }
-
- public String generateBoundary() {
- StringBuffer sb = new StringBuffer();
- sb.append("----");
- for (int i = 0; i < 30; i++) {
- sb.append(Integer.toString((int)(Math.random() * 35), 36));
- }
- return sb.toString().toUpperCase();
- }
-
- public String getPreamble() throws MessagingException {
- return mPreamble;
- }
-
- public void setPreamble(String preamble) throws MessagingException {
- this.mPreamble = preamble;
- }
-
- public String getContentType() throws MessagingException {
- return mContentType;
- }
-
- public void setSubType(String subType) throws MessagingException {
- this.mSubType = subType;
- mContentType = String.format("multipart/%s; boundary=\"%s\"", subType, mBoundary);
- }
-
- public void writeTo(OutputStream out) throws IOException, MessagingException {
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
-
- if (mPreamble != null) {
- writer.write(mPreamble + "\r\n");
- }
-
- for (int i = 0, count = mParts.size(); i < count; i++) {
- BodyPart bodyPart = (BodyPart)mParts.get(i);
- writer.write("--" + mBoundary + "\r\n");
- writer.flush();
- bodyPart.writeTo(out);
- writer.write("\r\n");
- }
-
- writer.write("--" + mBoundary + "--\r\n");
- writer.flush();
- }
-
- public InputStream getInputStream() throws MessagingException {
- return null;
- }
-}
diff --git a/src/com/android/email/mail/internet/MimeUtility.java b/src/com/android/email/mail/internet/MimeUtility.java
deleted file mode 100644
index 100a0abc5..000000000
--- a/src/com/android/email/mail/internet/MimeUtility.java
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.internet;
-
-import com.android.email.Email;
-import com.android.email.mail.Body;
-import com.android.email.mail.BodyPart;
-import com.android.email.mail.Message;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Multipart;
-import com.android.email.mail.Part;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.james.mime4j.decoder.Base64InputStream;
-import org.apache.james.mime4j.decoder.DecoderUtil;
-import org.apache.james.mime4j.decoder.QuotedPrintableInputStream;
-import org.apache.james.mime4j.util.CharsetUtil;
-
-import android.util.Log;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.regex.Pattern;
-
-public class MimeUtility {
- public static String unfold(String s) {
- if (s == null) {
- return null;
- }
- return s.replaceAll("\r|\n", "");
- }
-
- public static String decode(String s) {
- if (s == null) {
- return null;
- }
- return DecoderUtil.decodeEncodedWords(s);
- }
-
- public static String unfoldAndDecode(String s) {
- return decode(unfold(s));
- }
-
- // TODO implement proper foldAndEncode
- public static String foldAndEncode(String s) {
- return s;
- }
-
- /**
- * Returns the named parameter of a header field. If name is null the first
- * parameter is returned, or if there are no additional parameters in the
- * field the entire field is returned. Otherwise the named parameter is
- * searched for in a case insensitive fashion and returned. If the parameter
- * cannot be found the method returns null.
- *
- * @param header
- * @param name
- * @return
- */
- public static String getHeaderParameter(String header, String name) {
- if (header == null) {
- return null;
- }
- header = header.replaceAll("\r|\n", "");
- String[] parts = header.split(";");
- if (name == null) {
- return parts[0];
- }
- for (String part : parts) {
- if (part.trim().toLowerCase().startsWith(name.toLowerCase())) {
- String parameter = part.split("=", 2)[1].trim();
- if (parameter.startsWith("\"") && parameter.endsWith("\"")) {
- return parameter.substring(1, parameter.length() - 1);
- }
- else {
- return parameter;
- }
- }
- }
- return null;
- }
-
- public static Part findFirstPartByMimeType(Part part, String mimeType)
- throws MessagingException {
- if (part.getBody() instanceof Multipart) {
- Multipart multipart = (Multipart)part.getBody();
- for (int i = 0, count = multipart.getCount(); i < count; i++) {
- BodyPart bodyPart = multipart.getBodyPart(i);
- Part ret = findFirstPartByMimeType(bodyPart, mimeType);
- if (ret != null) {
- return ret;
- }
- }
- }
- else if (part.getMimeType().equalsIgnoreCase(mimeType)) {
- return part;
- }
- return null;
- }
-
- public static Part findPartByContentId(Part part, String contentId) throws Exception {
- if (part.getBody() instanceof Multipart) {
- Multipart multipart = (Multipart)part.getBody();
- for (int i = 0, count = multipart.getCount(); i < count; i++) {
- BodyPart bodyPart = multipart.getBodyPart(i);
- Part ret = findPartByContentId(bodyPart, contentId);
- if (ret != null) {
- return ret;
- }
- }
- }
- String[] header = part.getHeader("Content-ID");
- if (header != null) {
- for (String s : header) {
- if (s.equals(contentId)) {
- return part;
- }
- }
- }
- return null;
- }
-
- /**
- * Reads the Part's body and returns a String based on any charset conversion that needed
- * to be done.
- * @param part
- * @return
- * @throws IOException
- */
- public static String getTextFromPart(Part part) {
- try {
- if (part != null && part.getBody() != null) {
- InputStream in = part.getBody().getInputStream();
- String mimeType = part.getMimeType();
- if (mimeType != null && MimeUtility.mimeTypeMatches(mimeType, "text/*")) {
- /*
- * Now we read the part into a buffer for further processing. Because
- * the stream is now wrapped we'll remove any transfer encoding at this point.
- */
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- IOUtils.copy(in, out);
-
- byte[] bytes = out.toByteArray();
- in.close();
- out.close();
-
- String charset = getHeaderParameter(part.getContentType(), "charset");
- /*
- * We've got a text part, so let's see if it needs to be processed further.
- */
- if (charset != null) {
- /*
- * See if there is conversion from the MIME charset to the Java one.
- */
- charset = CharsetUtil.toJavaCharset(charset);
- }
- if (charset != null) {
- /*
- * We've got a charset encoding, so decode using it.
- */
- return new String(bytes, 0, bytes.length, charset);
- }
- else {
- /*
- * No encoding, so use us-ascii, which is the standard.
- */
- return new String(bytes, 0, bytes.length, "ASCII");
- }
- }
- }
-
- }
- catch (Exception e) {
- /*
- * If we are not able to process the body there's nothing we can do about it. Return
- * null and let the upper layers handle the missing content.
- */
- Log.e(Email.LOG_TAG, "Unable to getTextFromPart", e);
- }
- return null;
- }
-
- /**
- * Returns true if the given mimeType matches the matchAgainst specification. The comparison
- * ignores case and the matchAgainst string may include "*" for a wildcard (e.g. "image/*").
- *
- * @param mimeType A MIME type to check.
- * @param matchAgainst A MIME type to check against. May include wildcards.
- * @return true if the mimeType matches
- */
- public static boolean mimeTypeMatches(String mimeType, String matchAgainst) {
- Pattern p = Pattern.compile(matchAgainst.replaceAll("\\*", "\\.\\*"),
- Pattern.CASE_INSENSITIVE);
- return p.matcher(mimeType).matches();
- }
-
- /**
- * Returns true if the given mimeType matches any of the matchAgainst specifications. The
- * comparison ignores case and the matchAgainst strings may include "*" for a wildcard
- * (e.g. "image/*").
- *
- * @param mimeType A MIME type to check.
- * @param matchAgainst An array of MIME types to check against. May include wildcards.
- * @return true if the mimeType matches any of the matchAgainst strings
- */
- public static boolean mimeTypeMatches(String mimeType, String[] matchAgainst) {
- for (String matchType : matchAgainst) {
- if (mimeTypeMatches(mimeType, matchType)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Removes any content transfer encoding from the stream and returns a Body.
- */
- public static Body decodeBody(InputStream in, String contentTransferEncoding)
- throws IOException {
- /*
- * We'll remove any transfer encoding by wrapping the stream.
- */
- if (contentTransferEncoding != null) {
- contentTransferEncoding =
- MimeUtility.getHeaderParameter(contentTransferEncoding, null);
- if ("quoted-printable".equalsIgnoreCase(contentTransferEncoding)) {
- in = new QuotedPrintableInputStream(in);
- }
- else if ("base64".equalsIgnoreCase(contentTransferEncoding)) {
- in = new Base64InputStream(in);
- }
- }
-
- BinaryTempFileBody tempBody = new BinaryTempFileBody();
- OutputStream out = tempBody.getOutputStream();
- IOUtils.copy(in, out);
- out.close();
- return tempBody;
- }
-
- /**
- * An unfortunately named method that makes decisions about a Part (usually a Message)
- * as to which of it's children will be "viewable" and which will be attachments.
- * The method recursively sorts the viewables and attachments into seperate
- * lists for further processing.
- * @param part
- * @param viewables
- * @param attachments
- * @throws MessagingException
- */
- public static void collectParts(Part part, ArrayList<Part> viewables,
- ArrayList<Part> attachments) throws MessagingException {
- String disposition = part.getDisposition();
- String dispositionType = null;
- String dispositionFilename = null;
- if (disposition != null) {
- dispositionType = MimeUtility.getHeaderParameter(disposition, null);
- dispositionFilename = MimeUtility.getHeaderParameter(disposition, "filename");
- }
-
- /*
- * A best guess that this part is intended to be an attachment and not inline.
- */
- boolean attachment = ("attachment".equalsIgnoreCase(dispositionType))
- || (dispositionFilename != null)
- && (!"inline".equalsIgnoreCase(dispositionType));
-
- /*
- * If the part is Multipart but not alternative it's either mixed or
- * something we don't know about, which means we treat it as mixed
- * per the spec. We just process it's pieces recursively.
- */
- if (part.getBody() instanceof Multipart) {
- Multipart mp = (Multipart)part.getBody();
- for (int i = 0; i < mp.getCount(); i++) {
- collectParts(mp.getBodyPart(i), viewables, attachments);
- }
- }
- /*
- * If the part is an embedded message we just continue to process
- * it, pulling any viewables or attachments into the running list.
- */
- else if (part.getBody() instanceof Message) {
- Message message = (Message)part.getBody();
- collectParts(message, viewables, attachments);
- }
- /*
- * If the part is HTML and it got this far it's part of a mixed (et
- * al) and should be rendered inline.
- */
- else if ((!attachment) && (part.getMimeType().equalsIgnoreCase("text/html"))) {
- viewables.add(part);
- }
- /*
- * If the part is plain text and it got this far it's part of a
- * mixed (et al) and should be rendered inline.
- */
- else if ((!attachment) && (part.getMimeType().equalsIgnoreCase("text/plain"))) {
- viewables.add(part);
- }
- /*
- * Finally, if it's nothing else we will include it as an attachment.
- */
- else {
- attachments.add(part);
- }
- }
-}
diff --git a/src/com/android/email/mail/internet/TextBody.java b/src/com/android/email/mail/internet/TextBody.java
deleted file mode 100644
index 6b620c435..000000000
--- a/src/com/android/email/mail/internet/TextBody.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.internet;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-
-
-import com.android.email.codec.binary.Base64;
-import com.android.email.mail.Body;
-import com.android.email.mail.MessagingException;
-
-public class TextBody implements Body {
- String mBody;
-
- public TextBody(String body) {
- this.mBody = body;
- }
-
- public void writeTo(OutputStream out) throws IOException, MessagingException {
- byte[] bytes = mBody.getBytes("UTF-8");
- out.write(Base64.encodeBase64Chunked(bytes));
- }
-
- /**
- * Get the text of the body in it's unencoded format.
- * @return
- */
- public String getText() {
- return mBody;
- }
-
- /**
- * Returns an InputStream that reads this body's text in UTF-8 format.
- */
- public InputStream getInputStream() throws MessagingException {
- try {
- byte[] b = mBody.getBytes("UTF-8");
- return new ByteArrayInputStream(b);
- }
- catch (UnsupportedEncodingException usee) {
- return null;
- }
- }
-}
diff --git a/src/com/android/email/mail/store/ImapResponseParser.java b/src/com/android/email/mail/store/ImapResponseParser.java
deleted file mode 100644
index 4c7028b89..000000000
--- a/src/com/android/email/mail/store/ImapResponseParser.java
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.store;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Locale;
-
-import android.util.Config;
-import android.util.Log;
-
-import com.android.email.Email;
-import com.android.email.FixedLengthInputStream;
-import com.android.email.PeekableInputStream;
-import com.android.email.mail.MessagingException;
-
-public class ImapResponseParser {
- // DEBUG ONLY - Always check in as "false"
- private static boolean DEBUG_LOG_RAW_STREAM = false;
-
- // mDateTimeFormat is used only for parsing IMAP's FETCH ENVELOPE command, in which
- // en_US-like date format is used like "01-Jan-2009 11:20:39 -0800", so this should be
- // handled by Locale.US
- SimpleDateFormat mDateTimeFormat = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss Z", Locale.US);
- PeekableInputStream mIn;
- InputStream mActiveLiteral;
-
- public ImapResponseParser(PeekableInputStream in) {
- if (DEBUG_LOG_RAW_STREAM && Config.LOGD && Email.DEBUG) {
- in = new LoggingInputStream(in);
- }
- this.mIn = in;
- }
-
- /**
- * Reads the next response available on the stream and returns an
- * ImapResponse object that represents it.
- *
- * @return
- * @throws IOException
- */
- public ImapResponse readResponse() throws IOException {
- ImapResponse response = new ImapResponse();
- if (mActiveLiteral != null) {
- while (mActiveLiteral.read() != -1)
- ;
- mActiveLiteral = null;
- }
- int ch = mIn.peek();
- if (ch == '*') {
- parseUntaggedResponse();
- readTokens(response);
- } else if (ch == '+') {
- response.mCommandContinuationRequested =
- parseCommandContinuationRequest();
- readTokens(response);
- } else {
- response.mTag = parseTaggedResponse();
- readTokens(response);
- }
- if (Config.LOGD) {
- if (Email.DEBUG) {
- Log.d(Email.LOG_TAG, "<<< " + response.toString());
- }
- }
- return response;
- }
-
- private void readTokens(ImapResponse response) throws IOException {
- response.clear();
- Object token;
- while ((token = readToken()) != null) {
- if (response != null) {
- response.add(token);
- }
- if (mActiveLiteral != null) {
- break;
- }
- }
- response.mCompleted = token == null;
- }
-
- /**
- * Reads the next token of the response. The token can be one of: String -
- * for NIL, QUOTED, NUMBER, ATOM. InputStream - for LITERAL.
- * InputStream.available() returns the total length of the stream.
- * ImapResponseList - for PARENTHESIZED LIST. Can contain any of the above
- * elements including List.
- *
- * @return The next token in the response or null if there are no more
- * tokens.
- * @throws IOException
- */
- public Object readToken() throws IOException {
- while (true) {
- Object token = parseToken();
- if (token == null || !token.equals(")")) {
- return token;
- }
- }
- }
-
- private Object parseToken() throws IOException {
- if (mActiveLiteral != null) {
- while (mActiveLiteral.read() != -1)
- ;
- mActiveLiteral = null;
- }
- while (true) {
- int ch = mIn.peek();
- if (ch == '(') {
- return parseList();
- } else if (ch == ')') {
- expect(')');
- return ")";
- } else if (ch == '"') {
- return parseQuoted();
- } else if (ch == '{') {
- mActiveLiteral = parseLiteral();
- return mActiveLiteral;
- } else if (ch == ' ') {
- expect(' ');
- } else if (ch == '\r') {
- expect('\r');
- expect('\n');
- return null;
- } else if (ch == '\n') {
- expect('\n');
- return null;
- } else {
- return parseAtom();
- }
- }
- }
-
- private boolean parseCommandContinuationRequest() throws IOException {
- expect('+');
- expect(' ');
- return true;
- }
-
- // * OK [UIDNEXT 175] Predicted next UID
- private void parseUntaggedResponse() throws IOException {
- expect('*');
- expect(' ');
- }
-
- // 3 OK [READ-WRITE] Select completed.
- private String parseTaggedResponse() throws IOException {
- String tag = readStringUntil(' ');
- return tag;
- }
-
- private ImapList parseList() throws IOException {
- expect('(');
- ImapList list = new ImapList();
- Object token;
- while (true) {
- token = parseToken();
- if (token == null) {
- break;
- } else if (token instanceof InputStream) {
- list.add(token);
- break;
- } else if (token.equals(")")) {
- break;
- } else {
- list.add(token);
- }
- }
- return list;
- }
-
- private String parseAtom() throws IOException {
- StringBuffer sb = new StringBuffer();
- int ch;
- while (true) {
- ch = mIn.peek();
- if (ch == -1) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, "parseAtom(): end of stream reached");
- }
- throw new IOException("parseAtom(): end of stream reached");
- } else if (ch == '(' || ch == ')' || ch == '{' || ch == ' ' ||
- // docs claim that flags are \ atom but atom isn't supposed to
- // contain
- // * and some falgs contain *
- // ch == '%' || ch == '*' ||
- ch == '%' ||
- // TODO probably should not allow \ and should recognize
- // it as a flag instead
- // ch == '"' || ch == '\' ||
- ch == '"' || (ch >= 0x00 && ch <= 0x1f) || ch == 0x7f) {
- if (sb.length() == 0) {
- throw new IOException(String.format("parseAtom(): (%04x %c)", (int)ch, ch));
- }
- return sb.toString();
- } else {
- sb.append((char)mIn.read());
- }
- }
- }
-
- /**
- * A { has been read, read the rest of the size string, the space and then
- * notify the listener with an InputStream.
- *
- * @param mListener
- * @throws IOException
- */
- private InputStream parseLiteral() throws IOException {
- expect('{');
- int size = Integer.parseInt(readStringUntil('}'));
- expect('\r');
- expect('\n');
- FixedLengthInputStream fixed = new FixedLengthInputStream(mIn, size);
- return fixed;
- }
-
- /**
- * A " has been read, read to the end of the quoted string and notify the
- * listener.
- *
- * @param mListener
- * @throws IOException
- */
- private String parseQuoted() throws IOException {
- expect('"');
- return readStringUntil('"');
- }
-
- private String readStringUntil(char end) throws IOException {
- StringBuffer sb = new StringBuffer();
- int ch;
- while ((ch = mIn.read()) != -1) {
- if (ch == end) {
- return sb.toString();
- } else {
- sb.append((char)ch);
- }
- }
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, "readQuotedString(): end of stream reached");
- }
- throw new IOException("readQuotedString(): end of stream reached");
- }
-
- private int expect(char ch) throws IOException {
- int d;
- if ((d = mIn.read()) != ch) {
- if (d == -1 && Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, "expect(): end of stream reached");
- }
- throw new IOException(String.format("Expected %04x (%c) but got %04x (%c)", (int)ch,
- ch, d, (char)d));
- }
- return d;
- }
-
- /**
- * Represents an IMAP LIST response and is also the base class for the
- * ImapResponse.
- */
- public class ImapList extends ArrayList<Object> {
- public ImapList getList(int index) {
- return (ImapList)get(index);
- }
-
- public String getString(int index) {
- return (String)get(index);
- }
-
- public InputStream getLiteral(int index) {
- return (InputStream)get(index);
- }
-
- public int getNumber(int index) {
- return Integer.parseInt(getString(index));
- }
-
- public Date getDate(int index) throws MessagingException {
- try {
- return mDateTimeFormat.parse(getString(index));
- } catch (ParseException pe) {
- throw new MessagingException("Unable to parse IMAP datetime", pe);
- }
- }
-
- public Object getKeyedValue(Object key) {
- for (int i = 0, count = size(); i < count; i++) {
- if (get(i).equals(key)) {
- return get(i + 1);
- }
- }
- return null;
- }
-
- public ImapList getKeyedList(Object key) {
- return (ImapList)getKeyedValue(key);
- }
-
- public String getKeyedString(Object key) {
- return (String)getKeyedValue(key);
- }
-
- public InputStream getKeyedLiteral(Object key) {
- return (InputStream)getKeyedValue(key);
- }
-
- public int getKeyedNumber(Object key) {
- return Integer.parseInt(getKeyedString(key));
- }
-
- public Date getKeyedDate(Object key) throws MessagingException {
- try {
- String value = getKeyedString(key);
- if (value == null) {
- return null;
- }
- return mDateTimeFormat.parse(value);
- } catch (ParseException pe) {
- throw new MessagingException("Unable to parse IMAP datetime", pe);
- }
- }
- }
-
- /**
- * Represents a single response from the IMAP server. Tagged responses will
- * have a non-null tag. Untagged responses will have a null tag. The object
- * will contain all of the available tokens at the time the response is
- * received. In general, it will either contain all of the tokens of the
- * response or all of the tokens up until the first LITERAL. If the object
- * does not contain the entire response the caller must call more() to
- * continue reading the response until more returns false.
- */
- public class ImapResponse extends ImapList {
- private boolean mCompleted;
-
- boolean mCommandContinuationRequested;
- String mTag;
-
- public boolean more() throws IOException {
- if (mCompleted) {
- return false;
- }
- readTokens(this);
- return true;
- }
-
- public String getAlertText() {
- if (size() > 1 && "[ALERT]".equals(getString(1))) {
- StringBuffer sb = new StringBuffer();
- for (int i = 2, count = size(); i < count; i++) {
- sb.append(get(i).toString());
- sb.append(' ');
- }
- return sb.toString();
- } else {
- return null;
- }
- }
-
- public String toString() {
- return "#" + mTag + "# " + super.toString();
- }
- }
-
-
- /**
- * Simple class used for debugging only that affords us a view of the raw Imap stream,
- * in addition to the tokenized version.
- */
- private static class LoggingInputStream extends PeekableInputStream {
-
- PeekableInputStream mIn;
- StringBuilder mSb;
-
- public LoggingInputStream(PeekableInputStream in) {
- super(null);
- mIn = in;
- mSb = new StringBuilder();
- }
-
- /**
- * Collect chars as read, and log them when EOL reached.
- */
- @Override
- public int read() throws IOException {
- int oneByte = mIn.read();
- logRaw(oneByte);
- return oneByte;
- }
-
- /**
- * Collect chars as read, and log them when EOL reached.
- */
- @Override
- public int read(byte[] b, int offset, int length) throws IOException {
- int bytesRead = mIn.read(b, offset, length);
- int copyBytes = bytesRead;
- while (copyBytes > 0) {
- logRaw((char)b[offset]);
- copyBytes--;
- offset++;
- }
-
- return bytesRead;
- }
-
- /**
- * Pass-through any peeks
- */
- @Override
- public int peek() throws IOException {
- return mIn.peek();
- }
-
- /**
- * Write and clear the buffer
- */
- private void logRaw(int oneByte) {
- if (oneByte == '\r' || oneByte == '\n') {
- if (mSb.length() > 0) {
- Log.d(Email.LOG_TAG, "RAW " + mSb.toString());
- mSb = new StringBuilder();
- }
- } else {
- mSb.append((char)oneByte);
- }
- }
- }
-
-}
diff --git a/src/com/android/email/mail/store/ImapStore.java b/src/com/android/email/mail/store/ImapStore.java
deleted file mode 100644
index f4a27a129..000000000
--- a/src/com/android/email/mail/store/ImapStore.java
+++ /dev/null
@@ -1,1272 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.store;
-
-import com.android.email.Email;
-import com.android.email.PeekableInputStream;
-import com.android.email.Utility;
-import com.android.email.mail.AuthenticationFailedException;
-import com.android.email.mail.CertificateValidationException;
-import com.android.email.mail.FetchProfile;
-import com.android.email.mail.Flag;
-import com.android.email.mail.Folder;
-import com.android.email.mail.Message;
-import com.android.email.mail.MessageRetrievalListener;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Part;
-import com.android.email.mail.Store;
-import com.android.email.mail.Transport;
-import com.android.email.mail.internet.MimeBodyPart;
-import com.android.email.mail.internet.MimeHeader;
-import com.android.email.mail.internet.MimeMessage;
-import com.android.email.mail.internet.MimeMultipart;
-import com.android.email.mail.internet.MimeUtility;
-import com.android.email.mail.store.ImapResponseParser.ImapList;
-import com.android.email.mail.store.ImapResponseParser.ImapResponse;
-import com.android.email.mail.transport.CountingOutputStream;
-import com.android.email.mail.transport.EOLConvertingOutputStream;
-import com.android.email.mail.transport.MailTransport;
-import com.beetstra.jutf7.CharsetProvider;
-
-import android.util.Config;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-
-import javax.net.ssl.SSLException;
-
-/**
- * <pre>
- * TODO Need to start keeping track of UIDVALIDITY
- * TODO Need a default response handler for things like folder updates
- * TODO In fetch(), if we need a ImapMessage and were given
- * something else we can try to do a pre-fetch first.
- *
- * ftp://ftp.isi.edu/in-notes/rfc2683.txt When a client asks for
- * certain information in a FETCH command, the server may return the requested
- * information in any order, not necessarily in the order that it was requested.
- * Further, the server may return the information in separate FETCH responses
- * and may also return information that was not explicitly requested (to reflect
- * to the client changes in the state of the subject message).
- * </pre>
- */
-public class ImapStore extends Store {
- public static final int CONNECTION_SECURITY_NONE = 0;
- public static final int CONNECTION_SECURITY_TLS_OPTIONAL = 1;
- public static final int CONNECTION_SECURITY_TLS_REQUIRED = 2;
- public static final int CONNECTION_SECURITY_SSL_REQUIRED = 3;
- public static final int CONNECTION_SECURITY_SSL_OPTIONAL = 4;
-
- private static final Flag[] PERMANENT_FLAGS = { Flag.DELETED, Flag.SEEN };
-
- private Transport mRootTransport;
- private String mUsername;
- private String mPassword;
- private String mLoginPhrase;
- private String mPathPrefix;
-
- private LinkedList<ImapConnection> mConnections =
- new LinkedList<ImapConnection>();
-
- /**
- * Charset used for converting folder names to and from UTF-7 as defined by RFC 3501.
- */
- private Charset mModifiedUtf7Charset;
-
- /**
- * Cache of ImapFolder objects. ImapFolders are attached to a given folder on the server
- * and as long as their associated connection remains open they are reusable between
- * requests. This cache lets us make sure we always reuse, if possible, for a given
- * folder name.
- */
- private HashMap<String, ImapFolder> mFolderCache = new HashMap<String, ImapFolder>();
-
- /**
- * Allowed formats for the Uri:
- * imap://user:password@server:port CONNECTION_SECURITY_NONE
- * imap+tls://user:password@server:port CONNECTION_SECURITY_TLS_OPTIONAL
- * imap+tls+://user:password@server:port CONNECTION_SECURITY_TLS_REQUIRED
- * imap+ssl+://user:password@server:port CONNECTION_SECURITY_SSL_REQUIRED
- * imap+ssl://user:password@server:port CONNECTION_SECURITY_SSL_OPTIONAL
- *
- * @param uriString the Uri containing information to configure this store
- */
- public ImapStore(String uriString) throws MessagingException {
- URI uri;
- try {
- uri = new URI(uriString);
- } catch (URISyntaxException use) {
- throw new MessagingException("Invalid ImapStore URI", use);
- }
-
- String scheme = uri.getScheme();
- int connectionSecurity = Transport.CONNECTION_SECURITY_NONE;
- int defaultPort = -1;
- if (scheme.equals("imap")) {
- connectionSecurity = CONNECTION_SECURITY_NONE;
- defaultPort = 143;
- } else if (scheme.equals("imap+tls")) {
- connectionSecurity = CONNECTION_SECURITY_TLS_OPTIONAL;
- defaultPort = 143;
- } else if (scheme.equals("imap+tls+")) {
- connectionSecurity = CONNECTION_SECURITY_TLS_REQUIRED;
- defaultPort = 143;
- } else if (scheme.equals("imap+ssl+")) {
- connectionSecurity = CONNECTION_SECURITY_SSL_REQUIRED;
- defaultPort = 993;
- } else if (scheme.equals("imap+ssl")) {
- connectionSecurity = CONNECTION_SECURITY_SSL_OPTIONAL;
- defaultPort = 993;
- } else {
- throw new MessagingException("Unsupported protocol");
- }
-
- mRootTransport = new MailTransport("IMAP");
- mRootTransport.setUri(uri, defaultPort);
- mRootTransport.setSecurity(connectionSecurity);
-
- String[] userInfoParts = mRootTransport.getUserInfoParts();
- if (userInfoParts != null) {
- mUsername = userInfoParts[0];
- if (userInfoParts.length > 1) {
- mPassword = userInfoParts[1];
-
- // build the LOGIN string once (instead of over-and-over again.)
- // apply the quoting here around the built-up password
- mLoginPhrase = "LOGIN " + mUsername + " " + Utility.imapQuoted(mPassword);
- }
- }
-
- if ((uri.getPath() != null) && (uri.getPath().length() > 0)) {
- mPathPrefix = uri.getPath().substring(1);
- }
-
- mModifiedUtf7Charset = new CharsetProvider().charsetForName("X-RFC-3501");
- }
-
- /**
- * For testing only. Injects a different root transport (it will be copied using
- * newInstanceWithConfiguration() each time IMAP sets up a new channel). The transport
- * should already be set up and ready to use. Do not use for real code.
- * @param testTransport The Transport to inject and use for all future communication.
- */
- /* package */ void setTransport(Transport testTransport) {
- mRootTransport = testTransport;
- }
-
- @Override
- public Folder getFolder(String name) throws MessagingException {
- ImapFolder folder;
- synchronized (mFolderCache) {
- folder = mFolderCache.get(name);
- if (folder == null) {
- folder = new ImapFolder(name);
- mFolderCache.put(name, folder);
- }
- }
- return folder;
- }
-
-
- @Override
- public Folder[] getPersonalNamespaces() throws MessagingException {
- ImapConnection connection = getConnection();
- try {
- ArrayList<Folder> folders = new ArrayList<Folder>();
- List<ImapResponse> responses =
- connection.executeSimpleCommand(String.format("LIST \"\" \"%s*\"",
- mPathPrefix == null ? "" : mPathPrefix));
- for (ImapResponse response : responses) {
- if (response.get(0).equals("LIST")) {
- boolean includeFolder = true;
- String folder = decodeFolderName(response.getString(3));
- if (folder.equalsIgnoreCase("INBOX")) {
- continue;
- }
- ImapList attributes = response.getList(1);
- for (int i = 0, count = attributes.size(); i < count; i++) {
- String attribute = attributes.getString(i);
- if (attribute.equalsIgnoreCase("\\NoSelect")) {
- includeFolder = false;
- }
- }
- if (includeFolder) {
- folders.add(getFolder(folder));
- }
- }
- }
- folders.add(getFolder("INBOX"));
- return folders.toArray(new Folder[] {});
- } catch (IOException ioe) {
- connection.close();
- throw new MessagingException("Unable to get folder list.", ioe);
- } finally {
- releaseConnection(connection);
- }
- }
-
- @Override
- public void checkSettings() throws MessagingException {
- try {
- ImapConnection connection = new ImapConnection();
- connection.open();
- connection.close();
- }
- catch (IOException ioe) {
- throw new MessagingException(MessagingException.IOERROR, ioe.toString());
- }
- }
-
- /**
- * Gets a connection if one is available for reuse, or creates a new one if not.
- * @return
- */
- private ImapConnection getConnection() throws MessagingException {
- synchronized (mConnections) {
- ImapConnection connection = null;
- while ((connection = mConnections.poll()) != null) {
- try {
- connection.executeSimpleCommand("NOOP");
- break;
- }
- catch (IOException ioe) {
- connection.close();
- }
- }
- if (connection == null) {
- connection = new ImapConnection();
- }
- return connection;
- }
- }
-
- private void releaseConnection(ImapConnection connection) {
- mConnections.offer(connection);
- }
-
- private String encodeFolderName(String name) {
- try {
- ByteBuffer bb = mModifiedUtf7Charset.encode(name);
- byte[] b = new byte[bb.limit()];
- bb.get(b);
- return new String(b, "US-ASCII");
- }
- catch (UnsupportedEncodingException uee) {
- /*
- * The only thing that can throw this is getBytes("US-ASCII") and if US-ASCII doesn't
- * exist we're totally screwed.
- */
- throw new RuntimeException("Unabel to encode folder name: " + name, uee);
- }
- }
-
- private String decodeFolderName(String name) {
- /*
- * Convert the encoded name to US-ASCII, then pass it through the modified UTF-7
- * decoder and return the Unicode String.
- */
- try {
- byte[] encoded = name.getBytes("US-ASCII");
- CharBuffer cb = mModifiedUtf7Charset.decode(ByteBuffer.wrap(encoded));
- return cb.toString();
- }
- catch (UnsupportedEncodingException uee) {
- /*
- * The only thing that can throw this is getBytes("US-ASCII") and if US-ASCII doesn't
- * exist we're totally screwed.
- */
- throw new RuntimeException("Unable to decode folder name: " + name, uee);
- }
- }
-
- class ImapFolder extends Folder {
- private String mName;
- private int mMessageCount = -1;
- private ImapConnection mConnection;
- private OpenMode mMode;
- private boolean mExists;
-
- public ImapFolder(String name) {
- this.mName = name;
- }
-
- public void open(OpenMode mode) throws MessagingException {
- if (isOpen() && mMode == mode) {
- // Make sure the connection is valid. If it's not we'll close it down and continue
- // on to get a new one.
- try {
- mConnection.executeSimpleCommand("NOOP");
- return;
- }
- catch (IOException ioe) {
- ioExceptionHandler(mConnection, ioe);
- }
- }
- synchronized (this) {
- mConnection = getConnection();
- }
- // * FLAGS (\Answered \Flagged \Deleted \Seen \Draft NonJunk
- // $MDNSent)
- // * OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft
- // NonJunk $MDNSent \*)] Flags permitted.
- // * 23 EXISTS
- // * 0 RECENT
- // * OK [UIDVALIDITY 1125022061] UIDs valid
- // * OK [UIDNEXT 57576] Predicted next UID
- // 2 OK [READ-WRITE] Select completed.
- try {
- List<ImapResponse> responses = mConnection.executeSimpleCommand(
- String.format("SELECT \"%s\"",
- encodeFolderName(mName)));
- /*
- * If the command succeeds we expect the folder has been opened read-write
- * unless we are notified otherwise in the responses.
- */
- mMode = OpenMode.READ_WRITE;
-
- for (ImapResponse response : responses) {
- if (response.mTag == null && response.get(1).equals("EXISTS")) {
- mMessageCount = response.getNumber(0);
- }
- else if (response.mTag != null && response.size() >= 2) {
- if ("[READ-ONLY]".equalsIgnoreCase(response.getString(1))) {
- mMode = OpenMode.READ_ONLY;
- }
- else if ("[READ-WRITE]".equalsIgnoreCase(response.getString(1))) {
- mMode = OpenMode.READ_WRITE;
- }
- }
- }
-
- if (mMessageCount == -1) {
- throw new MessagingException(
- "Did not find message count during select");
- }
- mExists = true;
-
- } catch (IOException ioe) {
- throw ioExceptionHandler(mConnection, ioe);
- }
- }
-
- public boolean isOpen() {
- return mConnection != null;
- }
-
- @Override
- public OpenMode getMode() throws MessagingException {
- return mMode;
- }
-
- public void close(boolean expunge) {
- if (!isOpen()) {
- return;
- }
- // TODO implement expunge
- mMessageCount = -1;
- synchronized (this) {
- releaseConnection(mConnection);
- mConnection = null;
- }
- }
-
- public String getName() {
- return mName;
- }
-
- public boolean exists() throws MessagingException {
- if (mExists) {
- return true;
- }
- /*
- * This method needs to operate in the unselected mode as well as the selected mode
- * so we must get the connection ourselves if it's not there. We are specifically
- * not calling checkOpen() since we don't care if the folder is open.
- */
- ImapConnection connection = null;
- synchronized(this) {
- if (mConnection == null) {
- connection = getConnection();
- }
- else {
- connection = mConnection;
- }
- }
- try {
- connection.executeSimpleCommand(String.format("STATUS \"%s\" (UIDVALIDITY)",
- encodeFolderName(mName)));
- mExists = true;
- return true;
- }
- catch (MessagingException me) {
- return false;
- }
- catch (IOException ioe) {
- throw ioExceptionHandler(connection, ioe);
- }
- finally {
- if (mConnection == null) {
- releaseConnection(connection);
- }
- }
- }
-
- public boolean create(FolderType type) throws MessagingException {
- /*
- * This method needs to operate in the unselected mode as well as the selected mode
- * so we must get the connection ourselves if it's not there. We are specifically
- * not calling checkOpen() since we don't care if the folder is open.
- */
- ImapConnection connection = null;
- synchronized(this) {
- if (mConnection == null) {
- connection = getConnection();
- }
- else {
- connection = mConnection;
- }
- }
- try {
- connection.executeSimpleCommand(String.format("CREATE \"%s\"",
- encodeFolderName(mName)));
- return true;
- }
- catch (MessagingException me) {
- return false;
- }
- catch (IOException ioe) {
- throw ioExceptionHandler(mConnection, ioe);
- }
- finally {
- if (mConnection == null) {
- releaseConnection(connection);
- }
- }
- }
-
- @Override
- public void copyMessages(Message[] messages, Folder folder) throws MessagingException {
- checkOpen();
- String[] uids = new String[messages.length];
- for (int i = 0, count = messages.length; i < count; i++) {
- uids[i] = messages[i].getUid();
- }
- try {
- mConnection.executeSimpleCommand(String.format("UID COPY %s \"%s\"",
- Utility.combine(uids, ','),
- encodeFolderName(folder.getName())));
- }
- catch (IOException ioe) {
- throw ioExceptionHandler(mConnection, ioe);
- }
- }
-
- @Override
- public int getMessageCount() {
- return mMessageCount;
- }
-
- @Override
- public int getUnreadMessageCount() throws MessagingException {
- checkOpen();
- try {
- int unreadMessageCount = 0;
- List<ImapResponse> responses = mConnection.executeSimpleCommand(
- String.format("STATUS \"%s\" (UNSEEN)",
- encodeFolderName(mName)));
- for (ImapResponse response : responses) {
- if (response.mTag == null && response.get(0).equals("STATUS")) {
- ImapList status = response.getList(2);
- unreadMessageCount = status.getKeyedNumber("UNSEEN");
- }
- }
- return unreadMessageCount;
- }
- catch (IOException ioe) {
- throw ioExceptionHandler(mConnection, ioe);
- }
- }
-
- @Override
- public void delete(boolean recurse) throws MessagingException {
- throw new Error("ImapStore.delete() not yet implemented");
- }
-
- @Override
- public Message getMessage(String uid) throws MessagingException {
- checkOpen();
-
- try {
- try {
- List<ImapResponse> responses =
- mConnection.executeSimpleCommand(String.format("UID SEARCH UID %S", uid));
- for (ImapResponse response : responses) {
- if (response.mTag == null && response.get(0).equals("SEARCH")) {
- for (int i = 1, count = response.size(); i < count; i++) {
- if (uid.equals(response.get(i))) {
- return new ImapMessage(uid, this);
- }
- }
- }
- }
- }
- catch (MessagingException me) {
- return null;
- }
- }
- catch (IOException ioe) {
- throw ioExceptionHandler(mConnection, ioe);
- }
- return null;
- }
-
- @Override
- public Message[] getMessages(int start, int end, MessageRetrievalListener listener)
- throws MessagingException {
- if (start < 1 || end < 1 || end < start) {
- throw new MessagingException(
- String.format("Invalid message set %d %d",
- start, end));
- }
- checkOpen();
- ArrayList<Message> messages = new ArrayList<Message>();
- try {
- ArrayList<String> uids = new ArrayList<String>();
- List<ImapResponse> responses = mConnection
- .executeSimpleCommand(String.format("UID SEARCH %d:%d NOT DELETED", start, end));
- for (ImapResponse response : responses) {
- if (response.get(0).equals("SEARCH")) {
- for (int i = 1, count = response.size(); i < count; i++) {
- uids.add(response.getString(i));
- }
- }
- }
- for (int i = 0, count = uids.size(); i < count; i++) {
- if (listener != null) {
- listener.messageStarted(uids.get(i), i, count);
- }
- ImapMessage message = new ImapMessage(uids.get(i), this);
- messages.add(message);
- if (listener != null) {
- listener.messageFinished(message, i, count);
- }
- }
- } catch (IOException ioe) {
- throw ioExceptionHandler(mConnection, ioe);
- }
- return messages.toArray(new Message[] {});
- }
-
- public Message[] getMessages(MessageRetrievalListener listener) throws MessagingException {
- return getMessages(null, listener);
- }
-
- public Message[] getMessages(String[] uids, MessageRetrievalListener listener)
- throws MessagingException {
- checkOpen();
- ArrayList<Message> messages = new ArrayList<Message>();
- try {
- if (uids == null) {
- List<ImapResponse> responses = mConnection
- .executeSimpleCommand("UID SEARCH 1:* NOT DELETED");
- ArrayList<String> tempUids = new ArrayList<String>();
- for (ImapResponse response : responses) {
- if (response.get(0).equals("SEARCH")) {
- for (int i = 1, count = response.size(); i < count; i++) {
- tempUids.add(response.getString(i));
- }
- }
- }
- uids = tempUids.toArray(new String[] {});
- }
- for (int i = 0, count = uids.length; i < count; i++) {
- if (listener != null) {
- listener.messageStarted(uids[i], i, count);
- }
- ImapMessage message = new ImapMessage(uids[i], this);
- messages.add(message);
- if (listener != null) {
- listener.messageFinished(message, i, count);
- }
- }
- } catch (IOException ioe) {
- throw ioExceptionHandler(mConnection, ioe);
- }
- return messages.toArray(new Message[] {});
- }
-
- public void fetch(Message[] messages, FetchProfile fp, MessageRetrievalListener listener)
- throws MessagingException {
- if (messages == null || messages.length == 0) {
- return;
- }
- checkOpen();
- String[] uids = new String[messages.length];
- HashMap<String, Message> messageMap = new HashMap<String, Message>();
- for (int i = 0, count = messages.length; i < count; i++) {
- uids[i] = messages[i].getUid();
- messageMap.put(uids[i], messages[i]);
- }
-
- /*
- * Figure out what command we are going to run:
- * Flags - UID FETCH (FLAGS)
- * Envelope - UID FETCH ([FLAGS] INTERNALDATE UID RFC822.SIZE FLAGS BODY.PEEK[HEADER.FIELDS (date subject from content-type to cc)])
- *
- */
- LinkedHashSet<String> fetchFields = new LinkedHashSet<String>();
- fetchFields.add("UID");
- if (fp.contains(FetchProfile.Item.FLAGS)) {
- fetchFields.add("FLAGS");
- }
- if (fp.contains(FetchProfile.Item.ENVELOPE)) {
- fetchFields.add("INTERNALDATE");
- fetchFields.add("RFC822.SIZE");
- fetchFields.add("BODY.PEEK[HEADER.FIELDS (date subject from content-type to cc)]");
- }
- if (fp.contains(FetchProfile.Item.STRUCTURE)) {
- fetchFields.add("BODYSTRUCTURE");
- }
- if (fp.contains(FetchProfile.Item.BODY_SANE)) {
- fetchFields.add(String.format("BODY.PEEK[]<0.%d>", FETCH_BODY_SANE_SUGGESTED_SIZE));
- }
- if (fp.contains(FetchProfile.Item.BODY)) {
- fetchFields.add("BODY.PEEK[]");
- }
- for (Object o : fp) {
- if (o instanceof Part) {
- Part part = (Part) o;
- String partId = part.getHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA)[0];
- fetchFields.add("BODY.PEEK[" + partId + "]");
- }
- }
-
- try {
- String tag = mConnection.sendCommand(String.format("UID FETCH %s (%s)",
- Utility.combine(uids, ','),
- Utility.combine(fetchFields.toArray(new String[fetchFields.size()]), ' ')
- ), false);
- ImapResponse response;
- int messageNumber = 0;
- do {
- response = mConnection.readResponse();
-
- if (response.mTag == null && response.get(1).equals("FETCH")) {
- ImapList fetchList = (ImapList)response.getKeyedValue("FETCH");
- String uid = fetchList.getKeyedString("UID");
-
- Message message = messageMap.get(uid);
-
- if (listener != null) {
- listener.messageStarted(uid, messageNumber++, messageMap.size());
- }
-
- if (fp.contains(FetchProfile.Item.FLAGS)) {
- ImapList flags = fetchList.getKeyedList("FLAGS");
- ImapMessage imapMessage = (ImapMessage) message;
- if (flags != null) {
- for (int i = 0, count = flags.size(); i < count; i++) {
- String flag = flags.getString(i);
- if (flag.equals("\\Deleted")) {
- imapMessage.setFlagInternal(Flag.DELETED, true);
- }
- else if (flag.equals("\\Answered")) {
- imapMessage.setFlagInternal(Flag.ANSWERED, true);
- }
- else if (flag.equals("\\Seen")) {
- imapMessage.setFlagInternal(Flag.SEEN, true);
- }
- else if (flag.equals("\\Flagged")) {
- imapMessage.setFlagInternal(Flag.FLAGGED, true);
- }
- }
- }
- }
- if (fp.contains(FetchProfile.Item.ENVELOPE)) {
- Date internalDate = fetchList.getKeyedDate("INTERNALDATE");
- int size = fetchList.getKeyedNumber("RFC822.SIZE");
- InputStream headerStream = fetchList.getLiteral(fetchList.size() - 1);
-
- ImapMessage imapMessage = (ImapMessage) message;
-
- message.setInternalDate(internalDate);
- imapMessage.setSize(size);
- imapMessage.parse(headerStream);
- }
- if (fp.contains(FetchProfile.Item.STRUCTURE)) {
- ImapList bs = fetchList.getKeyedList("BODYSTRUCTURE");
- if (bs != null) {
- try {
- parseBodyStructure(bs, message, "TEXT");
- }
- catch (MessagingException e) {
- if (Config.LOGV) {
- Log.v(Email.LOG_TAG, "Error handling message", e);
- }
- message.setBody(null);
- }
- }
- }
- if (fp.contains(FetchProfile.Item.BODY)) {
- InputStream bodyStream = fetchList.getLiteral(fetchList.size() - 1);
- ImapMessage imapMessage = (ImapMessage) message;
- imapMessage.parse(bodyStream);
- }
- if (fp.contains(FetchProfile.Item.BODY_SANE)) {
- InputStream bodyStream = fetchList.getLiteral(fetchList.size() - 1);
- ImapMessage imapMessage = (ImapMessage) message;
- imapMessage.parse(bodyStream);
- }
- for (Object o : fp) {
- if (o instanceof Part) {
- Part part = (Part) o;
- InputStream bodyStream = fetchList.getLiteral(fetchList.size() - 1);
- String contentType = part.getContentType();
- String contentTransferEncoding = part.getHeader(
- MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING)[0];
- part.setBody(MimeUtility.decodeBody(
- bodyStream,
- contentTransferEncoding));
- }
- }
-
- if (listener != null) {
- listener.messageFinished(message, messageNumber, messageMap.size());
- }
- }
-
- while (response.more());
-
- } while (response.mTag == null);
- }
- catch (IOException ioe) {
- throw ioExceptionHandler(mConnection, ioe);
- }
- }
-
- @Override
- public Flag[] getPermanentFlags() throws MessagingException {
- return PERMANENT_FLAGS;
- }
-
- /**
- * Handle any untagged responses that the caller doesn't care to handle themselves.
- * @param responses
- */
- private void handleUntaggedResponses(List<ImapResponse> responses) {
- for (ImapResponse response : responses) {
- handleUntaggedResponse(response);
- }
- }
-
- /**
- * Handle an untagged response that the caller doesn't care to handle themselves.
- * @param response
- */
- private void handleUntaggedResponse(ImapResponse response) {
- if (response.mTag == null && response.get(1).equals("EXISTS")) {
- mMessageCount = response.getNumber(0);
- }
- }
-
- private void parseBodyStructure(ImapList bs, Part part, String id)
- throws MessagingException {
- if (bs.get(0) instanceof ImapList) {
- /*
- * This is a multipart/*
- */
- MimeMultipart mp = new MimeMultipart();
- for (int i = 0, count = bs.size(); i < count; i++) {
- if (bs.get(i) instanceof ImapList) {
- /*
- * For each part in the message we're going to add a new BodyPart and parse
- * into it.
- */
- ImapBodyPart bp = new ImapBodyPart();
- if (id.equals("TEXT")) {
- parseBodyStructure(bs.getList(i), bp, Integer.toString(i + 1));
- }
- else {
- parseBodyStructure(bs.getList(i), bp, id + "." + (i + 1));
- }
- mp.addBodyPart(bp);
- }
- else {
- /*
- * We've got to the end of the children of the part, so now we can find out
- * what type it is and bail out.
- */
- String subType = bs.getString(i);
- mp.setSubType(subType.toLowerCase());
- break;
- }
- }
- part.setBody(mp);
- }
- else{
- /*
- * This is a body. We need to add as much information as we can find out about
- * it to the Part.
- */
-
- /*
- body type
- body subtype
- body parameter parenthesized list
- body id
- body description
- body encoding
- body size
- */
-
-
- String type = bs.getString(0);
- String subType = bs.getString(1);
- String mimeType = (type + "/" + subType).toLowerCase();
-
- ImapList bodyParams = null;
- if (bs.get(2) instanceof ImapList) {
- bodyParams = bs.getList(2);
- }
- String encoding = bs.getString(5);
- int size = bs.getNumber(6);
-
- if (MimeUtility.mimeTypeMatches(mimeType, "message/rfc822")) {
-// A body type of type MESSAGE and subtype RFC822
-// contains, immediately after the basic fields, the
-// envelope structure, body structure, and size in
-// text lines of the encapsulated message.
-// [MESSAGE, RFC822, [NAME, Fwd: [#HTR-517941]: update plans at 1am Friday - Memory allocation - displayware.eml], NIL, NIL, 7BIT, 5974, NIL, [INLINE, [FILENAME*0, Fwd: [#HTR-517941]: update plans at 1am Friday - Memory all, FILENAME*1, ocation - displayware.eml]], NIL]
- /*
- * This will be caught by fetch and handled appropriately.
- */
- throw new MessagingException("BODYSTRUCTURE message/rfc822 not yet supported.");
- }
-
- /*
- * Set the content type with as much information as we know right now.
- */
- String contentType = String.format("%s", mimeType);
-
- if (bodyParams != null) {
- /*
- * If there are body params we might be able to get some more information out
- * of them.
- */
- for (int i = 0, count = bodyParams.size(); i < count; i += 2) {
- contentType += String.format(";\n %s=\"%s\"",
- bodyParams.getString(i),
- bodyParams.getString(i + 1));
- }
- }
-
- part.setHeader(MimeHeader.HEADER_CONTENT_TYPE, contentType);
-
- // Extension items
- ImapList bodyDisposition = null;
- if (("text".equalsIgnoreCase(type))
- && (bs.size() > 8)
- && (bs.get(9) instanceof ImapList)) {
- bodyDisposition = bs.getList(9);
- }
- else if (!("text".equalsIgnoreCase(type))
- && (bs.size() > 7)
- && (bs.get(8) instanceof ImapList)) {
- bodyDisposition = bs.getList(8);
- }
-
- String contentDisposition = "";
-
- if (bodyDisposition != null && bodyDisposition.size() > 0) {
- if (!"NIL".equalsIgnoreCase(bodyDisposition.getString(0))) {
- contentDisposition = bodyDisposition.getString(0).toLowerCase();
- }
-
- if ((bodyDisposition.size() > 1)
- && (bodyDisposition.get(1) instanceof ImapList)) {
- ImapList bodyDispositionParams = bodyDisposition.getList(1);
- /*
- * If there is body disposition information we can pull some more information
- * about the attachment out.
- */
- for (int i = 0, count = bodyDispositionParams.size(); i < count; i += 2) {
- contentDisposition += String.format(";\n %s=\"%s\"",
- bodyDispositionParams.getString(i).toLowerCase(),
- bodyDispositionParams.getString(i + 1));
- }
- }
- }
-
- if (MimeUtility.getHeaderParameter(contentDisposition, "size") == null) {
- contentDisposition += String.format(";\n size=%d", size);
- }
-
- /*
- * Set the content disposition containing at least the size. Attachment
- * handling code will use this down the road.
- */
- part.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, contentDisposition);
-
-
- /*
- * Set the Content-Transfer-Encoding header. Attachment code will use this
- * to parse the body.
- */
- part.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, encoding);
-
- if (part instanceof ImapMessage) {
- ((ImapMessage) part).setSize(size);
- }
- else if (part instanceof ImapBodyPart) {
- ((ImapBodyPart) part).setSize(size);
- }
- else {
- throw new MessagingException("Unknown part type " + part.toString());
- }
- part.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, id);
- }
-
- }
-
- /**
- * Appends the given messages to the selected folder. This implementation also determines
- * the new UID of the given message on the IMAP server and sets the Message's UID to the
- * new server UID.
- */
- public void appendMessages(Message[] messages) throws MessagingException {
- checkOpen();
- try {
- for (Message message : messages) {
- CountingOutputStream out = new CountingOutputStream();
- EOLConvertingOutputStream eolOut = new EOLConvertingOutputStream(out);
- message.writeTo(eolOut);
- eolOut.flush();
- mConnection.sendCommand(
- String.format("APPEND \"%s\" {%d}",
- encodeFolderName(mName),
- out.getCount()), false);
- ImapResponse response;
- do {
- response = mConnection.readResponse();
- if (response.mCommandContinuationRequested) {
- eolOut = new EOLConvertingOutputStream(mConnection.mTransport.getOutputStream());
- message.writeTo(eolOut);
- eolOut.write('\r');
- eolOut.write('\n');
- eolOut.flush();
- }
- else if (response.mTag == null) {
- handleUntaggedResponse(response);
- }
- while (response.more());
- } while(response.mTag == null);
-
- /*
- * Try to find the UID of the message we just appended using the
- * Message-ID header.
- */
- String[] messageIdHeader = message.getHeader("Message-ID");
- if (messageIdHeader == null || messageIdHeader.length == 0) {
- continue;
- }
- String messageId = messageIdHeader[0];
- List<ImapResponse> responses =
- mConnection.executeSimpleCommand(
- String.format("UID SEARCH (HEADER MESSAGE-ID %s)", messageId));
- for (ImapResponse response1 : responses) {
- if (response1.mTag == null && response1.get(0).equals("SEARCH")
- && response1.size() > 1) {
- message.setUid(response1.getString(1));
- }
- }
-
- }
- }
- catch (IOException ioe) {
- throw ioExceptionHandler(mConnection, ioe);
- }
- }
-
- public Message[] expunge() throws MessagingException {
- checkOpen();
- try {
- handleUntaggedResponses(mConnection.executeSimpleCommand("EXPUNGE"));
- } catch (IOException ioe) {
- throw ioExceptionHandler(mConnection, ioe);
- }
- return null;
- }
-
- public void setFlags(Message[] messages, Flag[] flags, boolean value)
- throws MessagingException {
- checkOpen();
- String[] uids = new String[messages.length];
- for (int i = 0, count = messages.length; i < count; i++) {
- uids[i] = messages[i].getUid();
- }
- ArrayList<String> flagNames = new ArrayList<String>();
- for (int i = 0, count = flags.length; i < count; i++) {
- Flag flag = flags[i];
- if (flag == Flag.SEEN) {
- flagNames.add("\\Seen");
- }
- else if (flag == Flag.DELETED) {
- flagNames.add("\\Deleted");
- }
- }
- try {
- mConnection.executeSimpleCommand(String.format("UID STORE %s %sFLAGS.SILENT (%s)",
- Utility.combine(uids, ','),
- value ? "+" : "-",
- Utility.combine(flagNames.toArray(new String[flagNames.size()]), ' ')));
- }
- catch (IOException ioe) {
- throw ioExceptionHandler(mConnection, ioe);
- }
- }
-
- private void checkOpen() throws MessagingException {
- if (!isOpen()) {
- throw new MessagingException("Folder " + mName + " is not open.");
- }
- }
-
- private MessagingException ioExceptionHandler(ImapConnection connection, IOException ioe)
- throws MessagingException {
- connection.close();
- close(false);
- return new MessagingException("IO Error", ioe);
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof ImapFolder) {
- return ((ImapFolder)o).mName.equals(mName);
- }
- return super.equals(o);
- }
- }
-
- /**
- * A cacheable class that stores the details for a single IMAP connection.
- */
- class ImapConnection {
- private Transport mTransport;
- private ImapResponseParser mParser;
- private int mNextCommandTag;
-
- public void open() throws IOException, MessagingException {
- PeekableInputStream mIn;
-
- if (mTransport != null && mTransport.isOpen()) {
- return;
- }
-
- mNextCommandTag = 1;
-
- try {
- // copy configuration into a clean transport, if necessary
- if (mTransport == null) {
- mTransport = mRootTransport.newInstanceWithConfiguration();
- }
-
- mTransport.open();
- mTransport.setSoTimeout(MailTransport.SOCKET_READ_TIMEOUT);
-
- mIn = new PeekableInputStream(mTransport.getInputStream());
- mParser = new ImapResponseParser(mIn);
-
- // BANNER
- mParser.readResponse();
-
- if (mTransport.canTryTlsSecurity()) {
- // CAPABILITY
- List<ImapResponse> responses = executeSimpleCommand("CAPABILITY");
- if (responses.size() != 2) {
- throw new MessagingException("Invalid CAPABILITY response received");
- }
- if (responses.get(0).contains("STARTTLS")) {
- // STARTTLS
- executeSimpleCommand("STARTTLS");
-
- mTransport.reopenTls();
- mTransport.setSoTimeout(MailTransport.SOCKET_READ_TIMEOUT);
- mIn = new PeekableInputStream(mTransport.getInputStream());
- mParser = new ImapResponseParser(mIn);
- } else if (mTransport.getSecurity() ==
- Transport.CONNECTION_SECURITY_TLS_REQUIRED) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, "TLS not supported but required");
- }
- throw new MessagingException(MessagingException.TLS_REQUIRED);
- }
- }
-
- try {
- // TODO eventually we need to add additional authentication
- // options such as SASL
- executeSimpleCommand(mLoginPhrase, true);
- } catch (ImapException ie) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, ie.toString());
- }
- throw new AuthenticationFailedException(ie.getAlertText(), ie);
-
- } catch (MessagingException me) {
- throw new AuthenticationFailedException(null, me);
- }
- } catch (SSLException e) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, e.toString());
- }
- throw new CertificateValidationException(e.getMessage(), e);
- } catch (IOException ioe) {
- // NOTE: Unlike similar code in POP3, I'm going to rethrow as-is. There is a lot
- // of other code here that catches IOException and I don't want to break it.
- // This catch is only here to enhance logging of connection-time issues.
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, ioe.toString());
- }
- throw ioe;
- }
- }
-
- public void close() {
-// if (isOpen()) {
-// try {
-// executeSimpleCommand("LOGOUT");
-// } catch (Exception e) {
-//
-// }
-// }
- if (mTransport != null) {
- mTransport.close();
- }
- }
-
- public ImapResponse readResponse() throws IOException, MessagingException {
- return mParser.readResponse();
- }
-
- /**
- * Send a single command to the server. The command will be preceded by an IMAP command
- * tag and followed by \r\n (caller need not supply them).
- *
- * @param command The command to send to the server
- * @param sensitive If true, the command will not be logged
- * @return Returns the command tag that was sent
- */
- public String sendCommand(String command, boolean sensitive)
- throws MessagingException, IOException {
- open();
- String tag = Integer.toString(mNextCommandTag++);
- String commandToSend = tag + " " + command;
- mTransport.writeLine(commandToSend, sensitive ? "[IMAP command redacted]" : null);
- return tag;
- }
-
- public List<ImapResponse> executeSimpleCommand(String command) throws IOException,
- ImapException, MessagingException {
- return executeSimpleCommand(command, false);
- }
-
- public List<ImapResponse> executeSimpleCommand(String command, boolean sensitive)
- throws IOException, ImapException, MessagingException {
- String tag = sendCommand(command, sensitive);
- ArrayList<ImapResponse> responses = new ArrayList<ImapResponse>();
- ImapResponse response;
- do {
- response = mParser.readResponse();
- responses.add(response);
- } while (response.mTag == null);
- if (response.size() < 1 || !response.get(0).equals("OK")) {
- throw new ImapException(response.toString(), response.getAlertText());
- }
- return responses;
- }
- }
-
- class ImapMessage extends MimeMessage {
- ImapMessage(String uid, Folder folder) throws MessagingException {
- this.mUid = uid;
- this.mFolder = folder;
- }
-
- public void setSize(int size) {
- this.mSize = size;
- }
-
- public void parse(InputStream in) throws IOException, MessagingException {
- super.parse(in);
- }
-
- public void setFlagInternal(Flag flag, boolean set) throws MessagingException {
- super.setFlag(flag, set);
- }
-
- @Override
- public void setFlag(Flag flag, boolean set) throws MessagingException {
- super.setFlag(flag, set);
- mFolder.setFlags(new Message[] { this }, new Flag[] { flag }, set);
- }
- }
-
- class ImapBodyPart extends MimeBodyPart {
- public ImapBodyPart() throws MessagingException {
- super();
- }
-
- public void setSize(int size) {
- this.mSize = size;
- }
- }
-
- class ImapException extends MessagingException {
- String mAlertText;
-
- public ImapException(String message, String alertText, Throwable throwable) {
- super(message, throwable);
- this.mAlertText = alertText;
- }
-
- public ImapException(String message, String alertText) {
- super(message);
- this.mAlertText = alertText;
- }
-
- public String getAlertText() {
- return mAlertText;
- }
-
- public void setAlertText(String alertText) {
- mAlertText = alertText;
- }
- }
-}
diff --git a/src/com/android/email/mail/store/LocalStore.java b/src/com/android/email/mail/store/LocalStore.java
deleted file mode 100644
index 773f9caaf..000000000
--- a/src/com/android/email/mail/store/LocalStore.java
+++ /dev/null
@@ -1,1194 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.store;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.UUID;
-
-import org.apache.commons.io.IOUtils;
-
-import android.app.Application;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.net.Uri;
-import android.util.Config;
-import android.util.Log;
-
-import com.android.email.Email;
-import com.android.email.Utility;
-import com.android.email.codec.binary.Base64OutputStream;
-import com.android.email.mail.Address;
-import com.android.email.mail.Body;
-import com.android.email.mail.FetchProfile;
-import com.android.email.mail.Flag;
-import com.android.email.mail.Folder;
-import com.android.email.mail.Message;
-import com.android.email.mail.MessageRetrievalListener;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Part;
-import com.android.email.mail.Store;
-import com.android.email.mail.Message.RecipientType;
-import com.android.email.mail.internet.MimeBodyPart;
-import com.android.email.mail.internet.MimeHeader;
-import com.android.email.mail.internet.MimeMessage;
-import com.android.email.mail.internet.MimeMultipart;
-import com.android.email.mail.internet.MimeUtility;
-import com.android.email.mail.internet.TextBody;
-import com.android.email.provider.AttachmentProvider;
-
-/**
- * <pre>
- * Implements a SQLite database backed local store for Messages.
- * </pre>
- */
-public class LocalStore extends Store {
- private static final int DB_VERSION = 18;
- private static final Flag[] PERMANENT_FLAGS = { Flag.DELETED, Flag.X_DESTROYED, Flag.SEEN };
-
- private String mPath;
- private SQLiteDatabase mDb;
- private File mAttachmentsDir;
- private Application mApplication;
-
- /**
- * @param uri local://localhost/path/to/database/uuid.db
- */
- public LocalStore(String _uri, Application application) throws MessagingException {
- mApplication = application;
- URI uri = null;
- try {
- uri = new URI(_uri);
- } catch (Exception e) {
- throw new MessagingException("Invalid uri for LocalStore");
- }
- if (!uri.getScheme().equals("local")) {
- throw new MessagingException("Invalid scheme");
- }
- mPath = uri.getPath();
-
- File parentDir = new File(mPath).getParentFile();
- if (!parentDir.exists()) {
- parentDir.mkdirs();
- }
- mDb = SQLiteDatabase.openOrCreateDatabase(mPath, null);
- if (mDb.getVersion() != DB_VERSION) {
- if (mDb.getVersion() < 18) {
- if (Config.LOGV) {
- Log.v(Email.LOG_TAG, String.format("Upgrading database from %d to %d", mDb
- .getVersion(), 18));
- }
- mDb.execSQL("DROP TABLE IF EXISTS folders");
- mDb.execSQL("CREATE TABLE folders (id INTEGER PRIMARY KEY, name TEXT, "
- + "last_updated INTEGER, unread_count INTEGER, visible_limit INTEGER)");
-
- mDb.execSQL("DROP TABLE IF EXISTS messages");
- mDb.execSQL("CREATE TABLE messages (id INTEGER PRIMARY KEY, folder_id INTEGER, uid TEXT, subject TEXT, "
- + "date INTEGER, flags TEXT, sender_list TEXT, to_list TEXT, cc_list TEXT, bcc_list TEXT, reply_to_list TEXT, "
- + "html_content TEXT, text_content TEXT, attachment_count INTEGER, internal_date INTEGER)");
-
- mDb.execSQL("DROP TABLE IF EXISTS attachments");
- mDb.execSQL("CREATE TABLE attachments (id INTEGER PRIMARY KEY, message_id INTEGER,"
- + "store_data TEXT, content_uri TEXT, size INTEGER, name TEXT,"
- + "mime_type TEXT)");
-
- mDb.execSQL("DROP TABLE IF EXISTS pending_commands");
- mDb.execSQL("CREATE TABLE pending_commands " +
- "(id INTEGER PRIMARY KEY, command TEXT, arguments TEXT)");
-
- mDb.execSQL("DROP TRIGGER IF EXISTS delete_folder");
- mDb.execSQL("CREATE TRIGGER delete_folder BEFORE DELETE ON folders BEGIN DELETE FROM messages WHERE old.id = folder_id; END;");
-
- mDb.execSQL("DROP TRIGGER IF EXISTS delete_message");
- mDb.execSQL("CREATE TRIGGER delete_message BEFORE DELETE ON messages BEGIN DELETE FROM attachments WHERE old.id = message_id; END;");
- mDb.setVersion(18);
- }
- if (mDb.getVersion() != DB_VERSION) {
- throw new Error("Database upgrade failed!");
- }
- }
- mAttachmentsDir = new File(mPath + "_att");
- if (!mAttachmentsDir.exists()) {
- mAttachmentsDir.mkdirs();
- }
- }
-
- @Override
- public Folder getFolder(String name) throws MessagingException {
- return new LocalFolder(name);
- }
-
- // TODO this takes about 260-300ms, seems slow.
- @Override
- public Folder[] getPersonalNamespaces() throws MessagingException {
- ArrayList<Folder> folders = new ArrayList<Folder>();
- Cursor cursor = null;
- try {
- cursor = mDb.rawQuery("SELECT name FROM folders", null);
- while (cursor.moveToNext()) {
- folders.add(new LocalFolder(cursor.getString(0)));
- }
- }
- finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- return folders.toArray(new Folder[] {});
- }
-
- @Override
- public void checkSettings() throws MessagingException {
- }
-
- /**
- * Delete the entire Store and it's backing database.
- */
- public void delete() {
- try {
- mDb.close();
- } catch (Exception e) {
-
- }
- try{
- File[] attachments = mAttachmentsDir.listFiles();
- for (File attachment : attachments) {
- if (attachment.exists()) {
- attachment.delete();
- }
- }
- if (mAttachmentsDir.exists()) {
- mAttachmentsDir.delete();
- }
- }
- catch (Exception e) {
- }
- try {
- new File(mPath).delete();
- }
- catch (Exception e) {
-
- }
- }
-
- /**
- * Deletes all cached attachments for the entire store.
- */
- public void pruneCachedAttachments() throws MessagingException {
- File[] files = mAttachmentsDir.listFiles();
- for (File file : files) {
- if (file.exists()) {
- try {
- Cursor cursor = null;
- try {
- cursor = mDb.query(
- "attachments",
- new String[] { "store_data" },
- "id = ?",
- new String[] { file.getName() },
- null,
- null,
- null);
- if (cursor.moveToNext()) {
- if (cursor.getString(0) == null) {
- /*
- * If the attachment has no store data it is not recoverable, so
- * we won't delete it.
- */
- continue;
- }
- }
- }
- finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- ContentValues cv = new ContentValues();
- cv.putNull("content_uri");
- mDb.update("attachments", cv, "id = ?", new String[] { file.getName() });
- }
- catch (Exception e) {
- /*
- * If the row has gone away before we got to mark it not-downloaded that's
- * okay.
- */
- }
- if (!file.delete()) {
- file.deleteOnExit();
- }
- }
- }
- }
-
- public void resetVisibleLimits() {
- ContentValues cv = new ContentValues();
- cv.put("visible_limit", Integer.toString(Email.DEFAULT_VISIBLE_LIMIT));
- mDb.update("folders", cv, null, null);
- }
-
- public ArrayList<PendingCommand> getPendingCommands() {
- Cursor cursor = null;
- try {
- cursor = mDb.query("pending_commands",
- new String[] { "id", "command", "arguments" },
- null,
- null,
- null,
- null,
- "id ASC");
- ArrayList<PendingCommand> commands = new ArrayList<PendingCommand>();
- while (cursor.moveToNext()) {
- PendingCommand command = new PendingCommand();
- command.mId = cursor.getLong(0);
- command.command = cursor.getString(1);
- String arguments = cursor.getString(2);
- command.arguments = arguments.split(",");
- for (int i = 0; i < command.arguments.length; i++) {
- command.arguments[i] = Utility.fastUrlDecode(command.arguments[i]);
- }
- commands.add(command);
- }
- return commands;
- }
- finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- }
-
- public void addPendingCommand(PendingCommand command) {
- try {
- for (int i = 0; i < command.arguments.length; i++) {
- command.arguments[i] = URLEncoder.encode(command.arguments[i], "UTF-8");
- }
- ContentValues cv = new ContentValues();
- cv.put("command", command.command);
- cv.put("arguments", Utility.combine(command.arguments, ','));
- mDb.insert("pending_commands", "command", cv);
- }
- catch (UnsupportedEncodingException usee) {
- throw new Error("Aparently UTF-8 has been lost to the annals of history.");
- }
- }
-
- public void removePendingCommand(PendingCommand command) {
- mDb.delete("pending_commands", "id = ?", new String[] { Long.toString(command.mId) });
- }
-
- public static class PendingCommand {
- private long mId;
- public String command;
- public String[] arguments;
-
- @Override
- public String toString() {
- StringBuffer sb = new StringBuffer();
- sb.append(command);
- sb.append("\n");
- for (String argument : arguments) {
- sb.append(" ");
- sb.append(argument);
- sb.append("\n");
- }
- return sb.toString();
- }
- }
-
- public class LocalFolder extends Folder {
- private String mName;
- private long mFolderId = -1;
- private int mUnreadMessageCount = -1;
- private int mVisibleLimit = -1;
-
- public LocalFolder(String name) {
- this.mName = name;
- }
-
- public long getId() {
- return mFolderId;
- }
-
- @Override
- public void open(OpenMode mode) throws MessagingException {
- if (isOpen()) {
- return;
- }
- if (!exists()) {
- create(FolderType.HOLDS_MESSAGES);
- }
- Cursor cursor = null;
- try {
- cursor = mDb.rawQuery("SELECT id, unread_count, visible_limit FROM folders "
- + "where folders.name = ?",
- new String[] {
- mName
- });
- cursor.moveToFirst();
- mFolderId = cursor.getInt(0);
- mUnreadMessageCount = cursor.getInt(1);
- mVisibleLimit = cursor.getInt(2);
- }
- finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- }
-
- @Override
- public boolean isOpen() {
- return mFolderId != -1;
- }
-
- @Override
- public OpenMode getMode() throws MessagingException {
- return OpenMode.READ_WRITE;
- }
-
- @Override
- public String getName() {
- return mName;
- }
-
- @Override
- public boolean exists() throws MessagingException {
- return Utility.arrayContains(getPersonalNamespaces(), this);
- }
-
- @Override
- public boolean create(FolderType type) throws MessagingException {
- if (exists()) {
- throw new MessagingException("Folder " + mName + " already exists.");
- }
- mDb.execSQL("INSERT INTO folders (name, visible_limit) VALUES (?, ?)", new Object[] {
- mName,
- 25
- });
- return true;
- }
-
- @Override
- public void close(boolean expunge) throws MessagingException {
- if (expunge) {
- expunge();
- }
- mFolderId = -1;
- }
-
- @Override
- public int getMessageCount() throws MessagingException {
- open(OpenMode.READ_WRITE);
- Cursor cursor = null;
- try {
- cursor = mDb.rawQuery("SELECT COUNT(*) FROM messages WHERE messages.folder_id = ?",
- new String[] {
- Long.toString(mFolderId)
- });
- cursor.moveToFirst();
- int messageCount = cursor.getInt(0);
- return messageCount;
- }
- finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- }
-
- @Override
- public int getUnreadMessageCount() throws MessagingException {
- open(OpenMode.READ_WRITE);
- return mUnreadMessageCount;
- }
-
-
- public void setUnreadMessageCount(int unreadMessageCount) throws MessagingException {
- open(OpenMode.READ_WRITE);
- mUnreadMessageCount = Math.max(0, unreadMessageCount);
- mDb.execSQL("UPDATE folders SET unread_count = ? WHERE id = ?",
- new Object[] { mUnreadMessageCount, mFolderId });
- }
-
- public int getVisibleLimit() throws MessagingException {
- open(OpenMode.READ_WRITE);
- return mVisibleLimit;
- }
-
-
- public void setVisibleLimit(int visibleLimit) throws MessagingException {
- open(OpenMode.READ_WRITE);
- mVisibleLimit = visibleLimit;
- mDb.execSQL("UPDATE folders SET visible_limit = ? WHERE id = ?",
- new Object[] { mVisibleLimit, mFolderId });
- }
-
-
- @Override
- public void fetch(Message[] messages, FetchProfile fp, MessageRetrievalListener listener)
- throws MessagingException {
- open(OpenMode.READ_WRITE);
- if (fp.contains(FetchProfile.Item.BODY)) {
- for (Message message : messages) {
- LocalMessage localMessage = (LocalMessage)message;
- Cursor cursor = null;
- localMessage.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "multipart/mixed");
- MimeMultipart mp = new MimeMultipart();
- mp.setSubType("mixed");
- localMessage.setBody(mp);
- try {
- cursor = mDb.rawQuery("SELECT html_content, text_content FROM messages "
- + "WHERE id = ?",
- new String[] { Long.toString(localMessage.mId) });
- cursor.moveToNext();
- String htmlContent = cursor.getString(0);
- String textContent = cursor.getString(1);
-
- if (htmlContent != null) {
- TextBody body = new TextBody(htmlContent);
- MimeBodyPart bp = new MimeBodyPart(body, "text/html");
- mp.addBodyPart(bp);
- }
-
- if (textContent != null) {
- TextBody body = new TextBody(textContent);
- MimeBodyPart bp = new MimeBodyPart(body, "text/plain");
- mp.addBodyPart(bp);
- }
- }
- finally {
- if (cursor != null) {
- cursor.close();
- }
- }
-
- try {
- cursor = mDb.query(
- "attachments",
- new String[] {
- "id",
- "size",
- "name",
- "mime_type",
- "store_data",
- "content_uri" },
- "message_id = ?",
- new String[] { Long.toString(localMessage.mId) },
- null,
- null,
- null);
-
- while (cursor.moveToNext()) {
- long id = cursor.getLong(0);
- int size = cursor.getInt(1);
- String name = cursor.getString(2);
- String type = cursor.getString(3);
- String storeData = cursor.getString(4);
- String contentUri = cursor.getString(5);
- Body body = null;
- if (contentUri != null) {
- body = new LocalAttachmentBody(Uri.parse(contentUri), mApplication);
- }
- MimeBodyPart bp = new LocalAttachmentBodyPart(body, id);
- bp.setHeader(MimeHeader.HEADER_CONTENT_TYPE,
- String.format("%s;\n name=\"%s\"",
- type,
- name));
- bp.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64");
- bp.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION,
- String.format("attachment;\n filename=\"%s\";\n size=%d",
- name,
- size));
-
- /*
- * HEADER_ANDROID_ATTACHMENT_STORE_DATA is a custom header we add to that
- * we can later pull the attachment from the remote store if neccesary.
- */
- bp.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, storeData);
-
- mp.addBodyPart(bp);
- }
- }
- finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- }
- }
- }
-
- private void populateMessageFromGetMessageCursor(LocalMessage message, Cursor cursor)
- throws MessagingException{
- message.setSubject(cursor.getString(0) == null ? "" : cursor.getString(0));
- Address[] from = Address.unpack(cursor.getString(1));
- if (from.length > 0) {
- message.setFrom(from[0]);
- }
- message.setSentDate(new Date(cursor.getLong(2)));
- message.setUid(cursor.getString(3));
- String flagList = cursor.getString(4);
- if (flagList != null && flagList.length() > 0) {
- String[] flags = flagList.split(",");
- try {
- for (String flag : flags) {
- message.setFlagInternal(Flag.valueOf(flag.toUpperCase()), true);
- }
- } catch (Exception e) {
- }
- }
- message.mId = cursor.getLong(5);
- message.setRecipients(RecipientType.TO, Address.unpack(cursor.getString(6)));
- message.setRecipients(RecipientType.CC, Address.unpack(cursor.getString(7)));
- message.setRecipients(RecipientType.BCC, Address.unpack(cursor.getString(8)));
- message.setReplyTo(Address.unpack(cursor.getString(9)));
- message.mAttachmentCount = cursor.getInt(10);
- message.setInternalDate(new Date(cursor.getLong(11)));
- }
-
- @Override
- public Message[] getMessages(int start, int end, MessageRetrievalListener listener)
- throws MessagingException {
- open(OpenMode.READ_WRITE);
- throw new MessagingException(
- "LocalStore.getMessages(int, int, MessageRetrievalListener) not yet implemented");
- }
-
- @Override
- public Message getMessage(String uid) throws MessagingException {
- open(OpenMode.READ_WRITE);
- LocalMessage message = new LocalMessage(uid, this);
- Cursor cursor = null;
- try {
- cursor = mDb.rawQuery(
- "SELECT subject, sender_list, date, uid, flags, id, to_list, cc_list, "
- + "bcc_list, reply_to_list, attachment_count, internal_date "
- + "FROM messages " + "WHERE uid = ? " + "AND folder_id = ?",
- new String[] {
- message.getUid(), Long.toString(mFolderId)
- });
- if (!cursor.moveToNext()) {
- return null;
- }
- populateMessageFromGetMessageCursor(message, cursor);
- }
- finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- return message;
- }
-
- @Override
- public Message[] getMessages(MessageRetrievalListener listener) throws MessagingException {
- open(OpenMode.READ_WRITE);
- ArrayList<Message> messages = new ArrayList<Message>();
- Cursor cursor = null;
- try {
- cursor = mDb.rawQuery(
- "SELECT subject, sender_list, date, uid, flags, id, to_list, cc_list, "
- + "bcc_list, reply_to_list, attachment_count, internal_date "
- + "FROM messages " + "WHERE folder_id = ?", new String[] {
- Long.toString(mFolderId)
- });
-
- while (cursor.moveToNext()) {
- LocalMessage message = new LocalMessage(null, this);
- populateMessageFromGetMessageCursor(message, cursor);
- messages.add(message);
- }
- }
- finally {
- if (cursor != null) {
- cursor.close();
- }
- }
-
- return messages.toArray(new Message[] {});
- }
-
- @Override
- public Message[] getMessages(String[] uids, MessageRetrievalListener listener)
- throws MessagingException {
- open(OpenMode.READ_WRITE);
- if (uids == null) {
- return getMessages(listener);
- }
- ArrayList<Message> messages = new ArrayList<Message>();
- for (String uid : uids) {
- messages.add(getMessage(uid));
- }
- return messages.toArray(new Message[] {});
- }
-
- @Override
- public void copyMessages(Message[] msgs, Folder folder) throws MessagingException {
- if (!(folder instanceof LocalFolder)) {
- throw new MessagingException("copyMessages called with incorrect Folder");
- }
- ((LocalFolder) folder).appendMessages(msgs, true);
- }
-
- /**
- * The method differs slightly from the contract; If an incoming message already has a uid
- * assigned and it matches the uid of an existing message then this message will replace the
- * old message. It is implemented as a delete/insert. This functionality is used in saving
- * of drafts and re-synchronization of updated server messages.
- */
- @Override
- public void appendMessages(Message[] messages) throws MessagingException {
- appendMessages(messages, false);
- }
-
- /**
- * The method differs slightly from the contract; If an incoming message already has a uid
- * assigned and it matches the uid of an existing message then this message will replace the
- * old message. It is implemented as a delete/insert. This functionality is used in saving
- * of drafts and re-synchronization of updated server messages.
- */
- public void appendMessages(Message[] messages, boolean copy) throws MessagingException {
- open(OpenMode.READ_WRITE);
- for (Message message : messages) {
- if (!(message instanceof MimeMessage)) {
- throw new Error("LocalStore can only store Messages that extend MimeMessage");
- }
-
- String uid = message.getUid();
- if (uid == null) {
- message.setUid("Local" + UUID.randomUUID().toString());
- }
- else {
- /*
- * The message may already exist in this Folder, so delete it first.
- */
- deleteAttachments(message.getUid());
- mDb.execSQL("DELETE FROM messages WHERE folder_id = ? AND uid = ?",
- new Object[] { mFolderId, message.getUid() });
- }
-
- ArrayList<Part> viewables = new ArrayList<Part>();
- ArrayList<Part> attachments = new ArrayList<Part>();
- MimeUtility.collectParts(message, viewables, attachments);
-
- StringBuffer sbHtml = new StringBuffer();
- StringBuffer sbText = new StringBuffer();
- for (Part viewable : viewables) {
- try {
- String text = MimeUtility.getTextFromPart(viewable);
- /*
- * Anything with MIME type text/html will be stored as such. Anything
- * else will be stored as text/plain.
- */
- if (viewable.getMimeType().equalsIgnoreCase("text/html")) {
- sbHtml.append(text);
- }
- else {
- sbText.append(text);
- }
- } catch (Exception e) {
- throw new MessagingException("Unable to get text for message part", e);
- }
- }
-
- try {
- ContentValues cv = new ContentValues();
- cv.put("uid", message.getUid());
- cv.put("subject", message.getSubject());
- cv.put("sender_list", Address.pack(message.getFrom()));
- cv.put("date", message.getSentDate() == null
- ? System.currentTimeMillis() : message.getSentDate().getTime());
- cv.put("flags", Utility.combine(message.getFlags(), ',').toUpperCase());
- cv.put("folder_id", mFolderId);
- cv.put("to_list", Address.pack(message.getRecipients(RecipientType.TO)));
- cv.put("cc_list", Address.pack(message.getRecipients(RecipientType.CC)));
- cv.put("bcc_list", Address.pack(message.getRecipients(RecipientType.BCC)));
- cv.put("html_content", sbHtml.length() > 0 ? sbHtml.toString() : null);
- cv.put("text_content", sbText.length() > 0 ? sbText.toString() : null);
- cv.put("reply_to_list", Address.pack(message.getReplyTo()));
- cv.put("attachment_count", attachments.size());
- cv.put("internal_date", message.getInternalDate() == null
- ? System.currentTimeMillis() : message.getInternalDate().getTime());
- long messageId = mDb.insert("messages", "uid", cv);
- for (Part attachment : attachments) {
- saveAttachment(messageId, attachment, copy);
- }
- } catch (Exception e) {
- throw new MessagingException("Error appending message", e);
- }
- }
- }
-
- /**
- * Update the given message in the LocalStore without first deleting the existing
- * message (contrast with appendMessages). This method is used to store changes
- * to the given message while updating attachments and not removing existing
- * attachment data.
- * TODO In the future this method should be combined with appendMessages since the Message
- * contains enough data to decide what to do.
- * @param message
- * @throws MessagingException
- */
- public void updateMessage(LocalMessage message) throws MessagingException {
- open(OpenMode.READ_WRITE);
- ArrayList<Part> viewables = new ArrayList<Part>();
- ArrayList<Part> attachments = new ArrayList<Part>();
- MimeUtility.collectParts(message, viewables, attachments);
-
- StringBuffer sbHtml = new StringBuffer();
- StringBuffer sbText = new StringBuffer();
- for (int i = 0, count = viewables.size(); i < count; i++) {
- Part viewable = viewables.get(i);
- try {
- String text = MimeUtility.getTextFromPart(viewable);
- /*
- * Anything with MIME type text/html will be stored as such. Anything
- * else will be stored as text/plain.
- */
- if (viewable.getMimeType().equalsIgnoreCase("text/html")) {
- sbHtml.append(text);
- }
- else {
- sbText.append(text);
- }
- } catch (Exception e) {
- throw new MessagingException("Unable to get text for message part", e);
- }
- }
-
- try {
- mDb.execSQL("UPDATE messages SET "
- + "uid = ?, subject = ?, sender_list = ?, date = ?, flags = ?, "
- + "folder_id = ?, to_list = ?, cc_list = ?, bcc_list = ?, "
- + "html_content = ?, text_content = ?, reply_to_list = ?, "
- + "attachment_count = ? WHERE id = ?",
- new Object[] {
- message.getUid(),
- message.getSubject(),
- Address.pack(message.getFrom()),
- message.getSentDate() == null ? System
- .currentTimeMillis() : message.getSentDate()
- .getTime(),
- Utility.combine(message.getFlags(), ',').toUpperCase(),
- mFolderId,
- Address.pack(message
- .getRecipients(RecipientType.TO)),
- Address.pack(message
- .getRecipients(RecipientType.CC)),
- Address.pack(message
- .getRecipients(RecipientType.BCC)),
- sbHtml.length() > 0 ? sbHtml.toString() : null,
- sbText.length() > 0 ? sbText.toString() : null,
- Address.pack(message.getReplyTo()),
- attachments.size(),
- message.mId
- });
-
- for (int i = 0, count = attachments.size(); i < count; i++) {
- Part attachment = attachments.get(i);
- saveAttachment(message.mId, attachment, false);
- }
- } catch (Exception e) {
- throw new MessagingException("Error appending message", e);
- }
- }
-
- /**
- * @param messageId
- * @param attachment
- * @param attachmentId -1 to create a new attachment or >= 0 to update an existing
- * @throws IOException
- * @throws MessagingException
- */
- private void saveAttachment(long messageId, Part attachment, boolean saveAsNew)
- throws IOException, MessagingException {
- long attachmentId = -1;
- Uri contentUri = null;
- int size = -1;
- File tempAttachmentFile = null;
-
- if ((!saveAsNew) && (attachment instanceof LocalAttachmentBodyPart)) {
- attachmentId = ((LocalAttachmentBodyPart) attachment).getAttachmentId();
- }
-
- if (attachment.getBody() != null) {
- Body body = attachment.getBody();
- if (body instanceof LocalAttachmentBody) {
- contentUri = ((LocalAttachmentBody) body).getContentUri();
- }
- else {
- /*
- * If the attachment has a body we're expected to save it into the local store
- * so we copy the data into a cached attachment file.
- */
- InputStream in = attachment.getBody().getInputStream();
- tempAttachmentFile = File.createTempFile("att", null, mAttachmentsDir);
- FileOutputStream out = new FileOutputStream(tempAttachmentFile);
- size = IOUtils.copy(in, out);
- in.close();
- out.close();
- }
- }
-
- if (size == -1) {
- /*
- * If the attachment is not yet downloaded see if we can pull a size
- * off the Content-Disposition.
- */
- String disposition = attachment.getDisposition();
- if (disposition != null) {
- String s = MimeUtility.getHeaderParameter(disposition, "size");
- if (s != null) {
- size = Integer.parseInt(s);
- }
- }
- }
- if (size == -1) {
- size = 0;
- }
-
- String storeData =
- Utility.combine(attachment.getHeader(
- MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA), ',');
-
- String name = MimeUtility.getHeaderParameter(attachment.getContentType(), "name");
-
- if (attachmentId == -1) {
- ContentValues cv = new ContentValues();
- cv.put("message_id", messageId);
- cv.put("content_uri", contentUri != null ? contentUri.toString() : null);
- cv.put("store_data", storeData);
- cv.put("size", size);
- cv.put("name", name);
- cv.put("mime_type", attachment.getMimeType());
-
- attachmentId = mDb.insert("attachments", "message_id", cv);
- }
- else {
- ContentValues cv = new ContentValues();
- cv.put("content_uri", contentUri != null ? contentUri.toString() : null);
- cv.put("size", size);
- mDb.update(
- "attachments",
- cv,
- "id = ?",
- new String[] { Long.toString(attachmentId) });
- }
-
- if (tempAttachmentFile != null) {
- File attachmentFile = new File(mAttachmentsDir, Long.toString(attachmentId));
- tempAttachmentFile.renameTo(attachmentFile);
- contentUri = AttachmentProvider.getAttachmentUri(
- new File(mPath).getName(),
- attachmentId);
- attachment.setBody(new LocalAttachmentBody(contentUri, mApplication));
- ContentValues cv = new ContentValues();
- cv.put("content_uri", contentUri != null ? contentUri.toString() : null);
- mDb.update(
- "attachments",
- cv,
- "id = ?",
- new String[] { Long.toString(attachmentId) });
- }
-
- if (attachment instanceof LocalAttachmentBodyPart) {
- ((LocalAttachmentBodyPart) attachment).setAttachmentId(attachmentId);
- }
- }
-
- /**
- * Changes the stored uid of the given message (using it's internal id as a key) to
- * the uid in the message.
- * @param message
- */
- public void changeUid(LocalMessage message) throws MessagingException {
- open(OpenMode.READ_WRITE);
- ContentValues cv = new ContentValues();
- cv.put("uid", message.getUid());
- mDb.update("messages", cv, "id = ?", new String[] { Long.toString(message.mId) });
- }
-
- @Override
- public void setFlags(Message[] messages, Flag[] flags, boolean value)
- throws MessagingException {
- open(OpenMode.READ_WRITE);
- for (Message message : messages) {
- message.setFlags(flags, value);
- }
- }
-
- @Override
- public Message[] expunge() throws MessagingException {
- open(OpenMode.READ_WRITE);
- ArrayList<Message> expungedMessages = new ArrayList<Message>();
- /*
- * epunge() doesn't do anything because deleted messages are saved for their uids
- * and really, really deleted messages are "Destroyed" and removed immediately.
- */
- return expungedMessages.toArray(new Message[] {});
- }
-
- @Override
- public void delete(boolean recurse) throws MessagingException {
- // We need to open the folder first to make sure we've got it's id
- open(OpenMode.READ_ONLY);
- Message[] messages = getMessages(null);
- for (Message message : messages) {
- deleteAttachments(message.getUid());
- }
- mDb.execSQL("DELETE FROM folders WHERE id = ?", new Object[] {
- Long.toString(mFolderId),
- });
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof LocalFolder) {
- return ((LocalFolder)o).mName.equals(mName);
- }
- return super.equals(o);
- }
-
- @Override
- public Flag[] getPermanentFlags() throws MessagingException {
- return PERMANENT_FLAGS;
- }
-
- private void deleteAttachments(String uid) throws MessagingException {
- open(OpenMode.READ_WRITE);
- Cursor messagesCursor = null;
- try {
- messagesCursor = mDb.query(
- "messages",
- new String[] { "id" },
- "folder_id = ? AND uid = ?",
- new String[] { Long.toString(mFolderId), uid },
- null,
- null,
- null);
- while (messagesCursor.moveToNext()) {
- long messageId = messagesCursor.getLong(0);
- Cursor attachmentsCursor = null;
- try {
- attachmentsCursor = mDb.query(
- "attachments",
- new String[] { "id" },
- "message_id = ?",
- new String[] { Long.toString(messageId) },
- null,
- null,
- null);
- while (attachmentsCursor.moveToNext()) {
- long attachmentId = attachmentsCursor.getLong(0);
- try{
- File file = new File(mAttachmentsDir, Long.toString(attachmentId));
- if (file.exists()) {
- file.delete();
- }
- }
- catch (Exception e) {
-
- }
- }
- }
- finally {
- if (attachmentsCursor != null) {
- attachmentsCursor.close();
- }
- }
- }
- }
- finally {
- if (messagesCursor != null) {
- messagesCursor.close();
- }
- }
- }
- }
-
- public class LocalMessage extends MimeMessage {
- private long mId;
- private int mAttachmentCount;
-
- LocalMessage(String uid, Folder folder) throws MessagingException {
- this.mUid = uid;
- this.mFolder = folder;
- }
-
- public int getAttachmentCount() {
- return mAttachmentCount;
- }
-
- public void parse(InputStream in) throws IOException, MessagingException {
- super.parse(in);
- }
-
- public void setFlagInternal(Flag flag, boolean set) throws MessagingException {
- super.setFlag(flag, set);
- }
-
- public long getId() {
- return mId;
- }
-
- public void setFlag(Flag flag, boolean set) throws MessagingException {
- if (flag == Flag.DELETED && set) {
- /*
- * If a message is being marked as deleted we want to clear out it's content
- * and attachments as well. Delete will not actually remove the row since we need
- * to retain the uid for synchronization purposes.
- */
-
- /*
- * Delete all of the messages' content to save space.
- */
- mDb.execSQL(
- "UPDATE messages SET " +
- "subject = NULL, " +
- "sender_list = NULL, " +
- "date = NULL, " +
- "to_list = NULL, " +
- "cc_list = NULL, " +
- "bcc_list = NULL, " +
- "html_content = NULL, " +
- "text_content = NULL, " +
- "reply_to_list = NULL " +
- "WHERE id = ?",
- new Object[] {
- mId
- });
-
- ((LocalFolder) mFolder).deleteAttachments(getUid());
-
- /*
- * Delete all of the messages' attachments to save space.
- */
- mDb.execSQL("DELETE FROM attachments WHERE id = ?",
- new Object[] {
- mId
- });
- }
- else if (flag == Flag.X_DESTROYED && set) {
- ((LocalFolder) mFolder).deleteAttachments(getUid());
- mDb.execSQL("DELETE FROM messages WHERE id = ?",
- new Object[] { mId });
- }
-
- /*
- * Update the unread count on the folder.
- */
- try {
- if (flag == Flag.DELETED || flag == Flag.X_DESTROYED || flag == Flag.SEEN) {
- LocalFolder folder = (LocalFolder)mFolder;
- if (set && !isSet(Flag.SEEN)) {
- folder.setUnreadMessageCount(folder.getUnreadMessageCount() - 1);
- }
- else if (!set && isSet(Flag.SEEN)) {
- folder.setUnreadMessageCount(folder.getUnreadMessageCount() + 1);
- }
- }
- }
- catch (MessagingException me) {
- Log.e(Email.LOG_TAG, "Unable to update LocalStore unread message count",
- me);
- throw new RuntimeException(me);
- }
-
- super.setFlag(flag, set);
- /*
- * Set the flags on the message.
- */
- mDb.execSQL("UPDATE messages " + "SET flags = ? " + "WHERE id = ?", new Object[] {
- Utility.combine(getFlags(), ',').toUpperCase(), mId
- });
- }
- }
-
- public class LocalAttachmentBodyPart extends MimeBodyPart {
- private long mAttachmentId = -1;
-
- public LocalAttachmentBodyPart(Body body, long attachmentId) throws MessagingException {
- super(body);
- mAttachmentId = attachmentId;
- }
-
- /**
- * Returns the local attachment id of this body, or -1 if it is not stored.
- * @return
- */
- public long getAttachmentId() {
- return mAttachmentId;
- }
-
- public void setAttachmentId(long attachmentId) {
- mAttachmentId = attachmentId;
- }
-
- public String toString() {
- return "" + mAttachmentId;
- }
- }
-
- public static class LocalAttachmentBody implements Body {
- private Application mApplication;
- private Uri mUri;
-
- public LocalAttachmentBody(Uri uri, Application application) {
- mApplication = application;
- mUri = uri;
- }
-
- public InputStream getInputStream() throws MessagingException {
- try {
- return mApplication.getContentResolver().openInputStream(mUri);
- }
- catch (FileNotFoundException fnfe) {
- /*
- * Since it's completely normal for us to try to serve up attachments that
- * have been blown away, we just return an empty stream.
- */
- return new ByteArrayInputStream(new byte[0]);
- }
- catch (IOException ioe) {
- throw new MessagingException("Invalid attachment.", ioe);
- }
- }
-
- public void writeTo(OutputStream out) throws IOException, MessagingException {
- InputStream in = getInputStream();
- Base64OutputStream base64Out = new Base64OutputStream(out);
- IOUtils.copy(in, base64Out);
- base64Out.close();
- }
-
- public Uri getContentUri() {
- return mUri;
- }
- }
-}
diff --git a/src/com/android/email/mail/store/Pop3Store.java b/src/com/android/email/mail/store/Pop3Store.java
deleted file mode 100644
index fc5bf772f..000000000
--- a/src/com/android/email/mail/store/Pop3Store.java
+++ /dev/null
@@ -1,951 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.store;
-
-import com.android.email.Email;
-import com.android.email.Utility;
-import com.android.email.mail.AuthenticationFailedException;
-import com.android.email.mail.FetchProfile;
-import com.android.email.mail.Flag;
-import com.android.email.mail.Folder;
-import com.android.email.mail.Message;
-import com.android.email.mail.MessageRetrievalListener;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Store;
-import com.android.email.mail.Transport;
-import com.android.email.mail.Folder.OpenMode;
-import com.android.email.mail.internet.MimeMessage;
-import com.android.email.mail.transport.MailTransport;
-
-import android.util.Config;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-
-public class Pop3Store extends Store {
- // All flags defining debug or development code settings must be FALSE
- // when code is checked in or released.
- private static boolean DEBUG_FORCE_SINGLE_LINE_UIDL = false;
-
- private static final Flag[] PERMANENT_FLAGS = { Flag.DELETED };
-
- private Transport mTransport;
- private String mUsername;
- private String mPassword;
- private HashMap<String, Folder> mFolders = new HashMap<String, Folder>();
-
-// /**
-// * Detected latency, used for usage scaling.
-// * Usage scaling occurs when it is neccesary to get information about
-// * messages that could result in large data loads. This value allows
-// * the code that loads this data to decide between using large downloads
-// * (high latency) or multiple round trips (low latency) to accomplish
-// * the same thing.
-// * Default is Integer.MAX_VALUE implying massive latency so that the large
-// * download method is used by default until latency data is collected.
-// */
-// private int mLatencyMs = Integer.MAX_VALUE;
-//
-// /**
-// * Detected throughput, used for usage scaling.
-// * Usage scaling occurs when it is neccesary to get information about
-// * messages that could result in large data loads. This value allows
-// * the code that loads this data to decide between using large downloads
-// * (high latency) or multiple round trips (low latency) to accomplish
-// * the same thing.
-// * Default is Integer.MAX_VALUE implying massive bandwidth so that the
-// * large download method is used by default until latency data is
-// * collected.
-// */
-// private int mThroughputKbS = Integer.MAX_VALUE;
-
- /**
- * pop3://user:password@server:port CONNECTION_SECURITY_NONE
- * pop3+tls://user:password@server:port CONNECTION_SECURITY_TLS_OPTIONAL
- * pop3+tls+://user:password@server:port CONNECTION_SECURITY_TLS_REQUIRED
- * pop3+ssl+://user:password@server:port CONNECTION_SECURITY_SSL_REQUIRED
- * pop3+ssl://user:password@server:port CONNECTION_SECURITY_SSL_OPTIONAL
- *
- * @param _uri
- */
- public Pop3Store(String _uri) throws MessagingException {
- URI uri;
- try {
- uri = new URI(_uri);
- } catch (URISyntaxException use) {
- throw new MessagingException("Invalid Pop3Store URI", use);
- }
-
- String scheme = uri.getScheme();
- int connectionSecurity = Transport.CONNECTION_SECURITY_NONE;
- int defaultPort = -1;
- if (scheme.equals(STORE_SCHEME_POP3)) {
- connectionSecurity = Transport.CONNECTION_SECURITY_NONE;
- defaultPort = 110;
- } else if (scheme.equals(STORE_SCHEME_POP3 + "+tls")) {
- connectionSecurity = Transport.CONNECTION_SECURITY_TLS_OPTIONAL;
- defaultPort = 110;
- } else if (scheme.equals(STORE_SCHEME_POP3 + "+tls+")) {
- connectionSecurity = Transport.CONNECTION_SECURITY_TLS_REQUIRED;
- defaultPort = 110;
- } else if (scheme.equals(STORE_SCHEME_POP3 + "+ssl+")) {
- connectionSecurity = Transport.CONNECTION_SECURITY_SSL_REQUIRED;
- defaultPort = 995;
- } else if (scheme.equals(STORE_SCHEME_POP3 + "+ssl")) {
- connectionSecurity = Transport.CONNECTION_SECURITY_SSL_OPTIONAL;
- defaultPort = 995;
- } else {
- throw new MessagingException("Unsupported protocol");
- }
-
- mTransport = new MailTransport("POP3");
- mTransport.setUri(uri, defaultPort);
- mTransport.setSecurity(connectionSecurity);
-
- String[] userInfoParts = mTransport.getUserInfoParts();
- if (userInfoParts != null) {
- mUsername = userInfoParts[0];
- if (userInfoParts.length > 1) {
- mPassword = userInfoParts[1];
- }
- }
- }
-
- /**
- * For testing only. Injects a different transport. The transport should already be set
- * up and ready to use. Do not use for real code.
- * @param testTransport The Transport to inject and use for all future communication.
- */
- /* package */ void setTransport(Transport testTransport) {
- mTransport = testTransport;
- }
-
- @Override
- public Folder getFolder(String name) throws MessagingException {
- Folder folder = mFolders.get(name);
- if (folder == null) {
- folder = new Pop3Folder(name);
- mFolders.put(folder.getName(), folder);
- }
- return folder;
- }
-
- @Override
- public Folder[] getPersonalNamespaces() throws MessagingException {
- return new Folder[] {
- getFolder("INBOX"),
- };
- }
-
- /**
- * Used by account setup to test if an account's settings are appropriate. The definition
- * of "checked" here is simply, can you log into the account and does it meet some minimum set
- * of feature requirements?
- *
- * @throws MessagingException if there was some problem with the account
- */
- @Override
- public void checkSettings() throws MessagingException {
- Pop3Folder folder = new Pop3Folder("INBOX");
- try {
- folder.open(OpenMode.READ_WRITE);
- folder.checkSettings();
- } finally {
- folder.close(false); // false == don't expunge anything
- }
- }
-
- class Pop3Folder extends Folder {
- private HashMap<String, Pop3Message> mUidToMsgMap = new HashMap<String, Pop3Message>();
- private HashMap<Integer, Pop3Message> mMsgNumToMsgMap = new HashMap<Integer, Pop3Message>();
- private HashMap<String, Integer> mUidToMsgNumMap = new HashMap<String, Integer>();
- private String mName;
- private int mMessageCount;
- private Pop3Capabilities mCapabilities;
-
- public Pop3Folder(String name) {
- this.mName = name;
- if (mName.equalsIgnoreCase("INBOX")) {
- mName = "INBOX";
- }
- }
-
- /**
- * Used by account setup to test if an account's settings are appropriate. Here, we run
- * an additional test to see if UIDL is supported on the server. If it's not we
- * can't service this account.
- *
- * @throws MessagingException if the account is not going to be useable
- */
- public void checkSettings() throws MessagingException {
- if (!mCapabilities.uidl) {
- try {
- UidlParser parser = new UidlParser();
- executeSimpleCommand("UIDL");
- // drain the entire output, so additional communications don't get confused.
- String response;
- while ((response = mTransport.readLine()) != null) {
- parser.parseMultiLine(response);
- if (parser.mEndOfMessage) {
- break;
- }
- }
- } catch (IOException ioe) {
- mTransport.close();
- throw new MessagingException(null, ioe);
- }
- }
- }
-
- @Override
- public synchronized void open(OpenMode mode) throws MessagingException {
- if (mTransport.isOpen()) {
- return;
- }
-
- if (!mName.equalsIgnoreCase("INBOX")) {
- throw new MessagingException("Folder does not exist");
- }
-
- try {
- mTransport.open();
-
- // Eat the banner
- executeSimpleCommand(null);
-
- mCapabilities = getCapabilities();
-
- if (mTransport.canTryTlsSecurity()) {
- if (mCapabilities.stls) {
- mTransport.writeLine("STLS", null);
- mTransport.reopenTls();
- } else if (mTransport.getSecurity() ==
- Transport.CONNECTION_SECURITY_TLS_REQUIRED) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, "TLS not supported but required");
- }
- throw new MessagingException(MessagingException.TLS_REQUIRED);
- }
- }
-
- try {
- executeSensitiveCommand("USER " + mUsername, "USER /redacted/");
- executeSensitiveCommand("PASS " + mPassword, "PASS /redacted/");
- } catch (MessagingException me) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, me.toString());
- }
- throw new AuthenticationFailedException(null, me);
- }
- } catch (IOException ioe) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, ioe.toString());
- }
- throw new MessagingException(MessagingException.IOERROR, ioe.toString());
- }
-
- try {
- String response = executeSimpleCommand("STAT");
- String[] parts = response.split(" ");
- mMessageCount = Integer.parseInt(parts[1]);
- }
- catch (IOException ioe) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, ioe.toString());
- }
- throw new MessagingException("POP3 STAT", ioe);
- }
- mUidToMsgMap.clear();
- mMsgNumToMsgMap.clear();
- mUidToMsgNumMap.clear();
- }
-
- @Override
- public OpenMode getMode() throws MessagingException {
- return OpenMode.READ_ONLY;
- }
-
- /**
- * Close the folder (and the transport below it).
- *
- * MUST NOT return any exceptions.
- *
- * @param expunge If true all deleted messages will be expunged (TODO - not implemented)
- */
- @Override
- public void close(boolean expunge) {
- try {
- executeSimpleCommand("QUIT");
- }
- catch (Exception e) {
- // ignore any problems here - just continue closing
- }
- mTransport.close();
- }
-
- @Override
- public String getName() {
- return mName;
- }
-
- @Override
- public boolean create(FolderType type) throws MessagingException {
- return false;
- }
-
- @Override
- public boolean exists() throws MessagingException {
- return mName.equalsIgnoreCase("INBOX");
- }
-
- @Override
- public int getMessageCount() {
- return mMessageCount;
- }
-
- @Override
- public int getUnreadMessageCount() throws MessagingException {
- return -1;
- }
-
- @Override
- public Message getMessage(String uid) throws MessagingException {
- Pop3Message message = mUidToMsgMap.get(uid);
- if (message == null) {
- message = new Pop3Message(uid, this);
- }
- return message;
- }
-
- @Override
- public Message[] getMessages(int start, int end, MessageRetrievalListener listener)
- throws MessagingException {
- if (start < 1 || end < 1 || end < start) {
- throw new MessagingException(String.format("Invalid message set %d %d",
- start, end));
- }
- try {
- indexMsgNums(start, end);
- } catch (IOException ioe) {
- mTransport.close();
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, ioe.toString());
- }
- throw new MessagingException("getMessages", ioe);
- }
- ArrayList<Message> messages = new ArrayList<Message>();
- int i = 0;
- for (int msgNum = start; msgNum <= end; msgNum++) {
- Pop3Message message = mMsgNumToMsgMap.get(msgNum);
- if (listener != null) {
- listener.messageStarted(message.getUid(), i++, (end - start) + 1);
- }
- messages.add(message);
- if (listener != null) {
- listener.messageFinished(message, i++, (end - start) + 1);
- }
- }
- return messages.toArray(new Message[messages.size()]);
- }
-
- /**
- * Ensures that the given message set (from start to end inclusive)
- * has been queried so that uids are available in the local cache.
- * @param start
- * @param end
- * @throws MessagingException
- * @throws IOException
- */
- private void indexMsgNums(int start, int end)
- throws MessagingException, IOException {
- int unindexedMessageCount = 0;
- for (int msgNum = start; msgNum <= end; msgNum++) {
- if (mMsgNumToMsgMap.get(msgNum) == null) {
- unindexedMessageCount++;
- }
- }
- if (unindexedMessageCount == 0) {
- return;
- }
- UidlParser parser = new UidlParser();
- if (DEBUG_FORCE_SINGLE_LINE_UIDL ||
- (unindexedMessageCount < 50 && mMessageCount > 5000)) {
- /*
- * In extreme cases we'll do a UIDL command per message instead of a bulk
- * download.
- */
- for (int msgNum = start; msgNum <= end; msgNum++) {
- Pop3Message message = mMsgNumToMsgMap.get(msgNum);
- if (message == null) {
- String response = executeSimpleCommand("UIDL " + msgNum);
- parser.parseSingleLine(response);
- message = new Pop3Message(parser.mUniqueId, this);
- indexMessage(msgNum, message);
- }
- }
- }
- else {
- String response = executeSimpleCommand("UIDL");
- while ((response = mTransport.readLine()) != null) {
- parser.parseMultiLine(response);
- if (parser.mEndOfMessage) {
- break;
- }
- int msgNum = parser.mMessageNumber;
- if (msgNum >= start && msgNum <= end) {
- Pop3Message message = mMsgNumToMsgMap.get(msgNum);
- if (message == null) {
- message = new Pop3Message(parser.mUniqueId, this);
- indexMessage(msgNum, message);
- }
- }
- }
- }
- }
-
- private void indexUids(ArrayList<String> uids)
- throws MessagingException, IOException {
- HashSet<String> unindexedUids = new HashSet<String>();
- for (String uid : uids) {
- if (mUidToMsgMap.get(uid) == null) {
- unindexedUids.add(uid);
- }
- }
- if (unindexedUids.size() == 0) {
- return;
- }
- /*
- * If we are missing uids in the cache the only sure way to
- * get them is to do a full UIDL list. A possible optimization
- * would be trying UIDL for the latest X messages and praying.
- */
- UidlParser parser = new UidlParser();
- String response = executeSimpleCommand("UIDL");
- while ((response = mTransport.readLine()) != null) {
- parser.parseMultiLine(response);
- if (parser.mEndOfMessage) {
- break;
- }
- if (unindexedUids.contains(parser.mUniqueId)) {
- Pop3Message message = mUidToMsgMap.get(parser.mUniqueId);
- if (message == null) {
- message = new Pop3Message(parser.mUniqueId, this);
- }
- indexMessage(parser.mMessageNumber, message);
- }
- }
- }
-
- /**
- * Simple parser class for UIDL messages.
- *
- * <p>NOTE: In variance with RFC 1939, we allow multiple whitespace between the
- * message-number and unique-id fields. This provides greater compatibility with some
- * non-compliant POP3 servers, e.g. mail.comcast.net.
- */
- /* package */ class UidlParser {
-
- /**
- * Caller can read back message-number from this field
- */
- public int mMessageNumber;
- /**
- * Caller can read back unique-id from this field
- */
- public String mUniqueId;
- /**
- * True if the response was "end-of-message"
- */
- public boolean mEndOfMessage;
- /**
- * True if an error was reported
- */
- public boolean mErr;
-
- /**
- * Construct & Initialize
- */
- public UidlParser() {
- mErr = true;
- }
-
- /**
- * Parse a single-line response. This is returned from a command of the form
- * "UIDL msg-num" and will be formatted as: "+OK msg-num unique-id" or
- * "-ERR diagnostic text"
- *
- * @param response The string returned from the server
- * @return true if the string parsed as expected (e.g. no syntax problems)
- */
- public boolean parseSingleLine(String response) {
- mErr = false;
- char first = response.charAt(0);
- if (first == '+') {
- String[] uidParts = response.split(" +");
- if (uidParts.length >= 3) {
- mMessageNumber = Integer.parseInt(uidParts[1]);
- mUniqueId = uidParts[2];
- mEndOfMessage = true;
- return true;
- }
- } else if (first == '-') {
- mErr = true;
- return true;
- }
- return false;
- }
-
- /**
- * Parse a multi-line response. This is returned from a command of the form
- * "UIDL" and will be formatted as: "." or "msg-num unique-id".
- *
- * @param response The string returned from the server
- * @return true if the string parsed as expected (e.g. no syntax problems)
- */
- public boolean parseMultiLine(String response) {
- mErr = false;
- char first = response.charAt(0);
- if (first == '.') {
- mEndOfMessage = true;
- return true;
- } else {
- String[] uidParts = response.split(" +");
- if (uidParts.length >= 2) {
- mMessageNumber = Integer.parseInt(uidParts[0]);
- mUniqueId = uidParts[1];
- mEndOfMessage = false;
- return true;
- }
- }
- return false;
- }
- }
-
- private void indexMessage(int msgNum, Pop3Message message) {
- mMsgNumToMsgMap.put(msgNum, message);
- mUidToMsgMap.put(message.getUid(), message);
- mUidToMsgNumMap.put(message.getUid(), msgNum);
- }
-
- @Override
- public Message[] getMessages(MessageRetrievalListener listener) throws MessagingException {
- throw new UnsupportedOperationException("Pop3Folder.getMessage(MessageRetrievalListener)");
- }
-
- @Override
- public Message[] getMessages(String[] uids, MessageRetrievalListener listener)
- throws MessagingException {
- throw new UnsupportedOperationException("Pop3Folder.getMessage(MessageRetrievalListener)");
- }
-
- /**
- * Fetch the items contained in the FetchProfile into the given set of
- * Messages in as efficient a manner as possible.
- * @param messages
- * @param fp
- * @throws MessagingException
- */
- public void fetch(Message[] messages, FetchProfile fp, MessageRetrievalListener listener)
- throws MessagingException {
- if (messages == null || messages.length == 0) {
- return;
- }
- ArrayList<String> uids = new ArrayList<String>();
- for (Message message : messages) {
- uids.add(message.getUid());
- }
- try {
- indexUids(uids);
- if (fp.contains(FetchProfile.Item.ENVELOPE)) {
- // Note: We never pass the listener for the ENVELOPE call, because we're going
- // to be calling the listener below in the per-message loop.
- fetchEnvelope(messages, null);
- }
- }
- catch (IOException ioe) {
- mTransport.close();
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, ioe.toString());
- }
- throw new MessagingException("fetch", ioe);
- }
- for (int i = 0, count = messages.length; i < count; i++) {
- Message message = messages[i];
- if (!(message instanceof Pop3Message)) {
- throw new MessagingException("Pop3Store.fetch called with non-Pop3 Message");
- }
- Pop3Message pop3Message = (Pop3Message)message;
- try {
- if (listener != null) {
- listener.messageStarted(pop3Message.getUid(), i, count);
- }
- if (fp.contains(FetchProfile.Item.BODY)) {
- fetchBody(pop3Message, -1);
- }
- else if (fp.contains(FetchProfile.Item.BODY_SANE)) {
- /*
- * To convert the suggested download size we take the size
- * divided by the maximum line size (76).
- */
- fetchBody(pop3Message,
- FETCH_BODY_SANE_SUGGESTED_SIZE / 76);
- }
- else if (fp.contains(FetchProfile.Item.STRUCTURE)) {
- /*
- * If the user is requesting STRUCTURE we are required to set the body
- * to null since we do not support the function.
- */
- pop3Message.setBody(null);
- }
- if (listener != null) {
- listener.messageFinished(message, i, count);
- }
- } catch (IOException ioe) {
- mTransport.close();
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, ioe.toString());
- }
- throw new MessagingException("Unable to fetch message", ioe);
- }
- }
- }
-
- private void fetchEnvelope(Message[] messages,
- MessageRetrievalListener listener) throws IOException, MessagingException {
- int unsizedMessages = 0;
- for (Message message : messages) {
- if (message.getSize() == -1) {
- unsizedMessages++;
- }
- }
- if (unsizedMessages == 0) {
- return;
- }
- if (unsizedMessages < 50 && mMessageCount > 5000) {
- /*
- * In extreme cases we'll do a command per message instead of a bulk request
- * to hopefully save some time and bandwidth.
- */
- for (int i = 0, count = messages.length; i < count; i++) {
- Message message = messages[i];
- if (!(message instanceof Pop3Message)) {
- throw new MessagingException("Pop3Store.fetch called with non-Pop3 Message");
- }
- Pop3Message pop3Message = (Pop3Message)message;
- if (listener != null) {
- listener.messageStarted(pop3Message.getUid(), i, count);
- }
- String response = executeSimpleCommand(String.format("LIST %d",
- mUidToMsgNumMap.get(pop3Message.getUid())));
- String[] listParts = response.split(" ");
- int msgNum = Integer.parseInt(listParts[1]);
- int msgSize = Integer.parseInt(listParts[2]);
- pop3Message.setSize(msgSize);
- if (listener != null) {
- listener.messageFinished(pop3Message, i, count);
- }
- }
- }
- else {
- HashSet<String> msgUidIndex = new HashSet<String>();
- for (Message message : messages) {
- msgUidIndex.add(message.getUid());
- }
- int i = 0, count = messages.length;
- String response = executeSimpleCommand("LIST");
- while ((response = mTransport.readLine()) != null) {
- if (response.equals(".")) {
- break;
- }
- String[] listParts = response.split(" ");
- int msgNum = Integer.parseInt(listParts[0]);
- int msgSize = Integer.parseInt(listParts[1]);
- Pop3Message pop3Message = mMsgNumToMsgMap.get(msgNum);
- if (pop3Message != null && msgUidIndex.contains(pop3Message.getUid())) {
- if (listener != null) {
- listener.messageStarted(pop3Message.getUid(), i, count);
- }
- pop3Message.setSize(msgSize);
- if (listener != null) {
- listener.messageFinished(pop3Message, i, count);
- }
- i++;
- }
- }
- }
- }
-
- /**
- * Fetches the body of the given message, limiting the stored data
- * to the specified number of lines. If lines is -1 the entire message
- * is fetched. This is implemented with RETR for lines = -1 or TOP
- * for any other value. If the server does not support TOP it is
- * emulated with RETR and extra lines are thrown away.
- * @param message
- * @param lines
- */
- private void fetchBody(Pop3Message message, int lines)
- throws IOException, MessagingException {
- String response = null;
- if (lines == -1 || !mCapabilities.top) {
- response = executeSimpleCommand(String.format("RETR %d",
- mUidToMsgNumMap.get(message.getUid())));
- }
- else {
- response = executeSimpleCommand(String.format("TOP %d %d",
- mUidToMsgNumMap.get(message.getUid()),
- lines));
- }
- if (response != null) {
- try {
- message.parse(new Pop3ResponseInputStream(mTransport.getInputStream()));
- }
- catch (MessagingException me) {
- /*
- * If we're only downloading headers it's possible
- * we'll get a broken MIME message which we're not
- * real worried about. If we've downloaded the body
- * and can't parse it we need to let the user know.
- */
- if (lines == -1) {
- throw me;
- }
- }
- }
- }
-
- @Override
- public Flag[] getPermanentFlags() throws MessagingException {
- return PERMANENT_FLAGS;
- }
-
- public void appendMessages(Message[] messages) throws MessagingException {
- }
-
- public void delete(boolean recurse) throws MessagingException {
- }
-
- public Message[] expunge() throws MessagingException {
- return null;
- }
-
- public void setFlags(Message[] messages, Flag[] flags, boolean value)
- throws MessagingException {
- if (!value || !Utility.arrayContains(flags, Flag.DELETED)) {
- /*
- * The only flagging we support is setting the Deleted flag.
- */
- return;
- }
- try {
- for (Message message : messages) {
- executeSimpleCommand(String.format("DELE %s",
- mUidToMsgNumMap.get(message.getUid())));
- }
- }
- catch (IOException ioe) {
- mTransport.close();
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, ioe.toString());
- }
- throw new MessagingException("setFlags()", ioe);
- }
- }
-
- @Override
- public void copyMessages(Message[] msgs, Folder folder) throws MessagingException {
- throw new UnsupportedOperationException("copyMessages is not supported in POP3");
- }
-
-// private boolean isRoundTripModeSuggested() {
-// long roundTripMethodMs =
-// (uncachedMessageCount * 2 * mLatencyMs);
-// long bulkMethodMs =
-// (mMessageCount * 58) / (mThroughputKbS * 1024 / 8) * 1000;
-// }
-
- private Pop3Capabilities getCapabilities() throws IOException, MessagingException {
- Pop3Capabilities capabilities = new Pop3Capabilities();
- try {
- String response = executeSimpleCommand("CAPA");
- while ((response = mTransport.readLine()) != null) {
- if (response.equals(".")) {
- break;
- }
- if (response.equalsIgnoreCase("STLS")){
- capabilities.stls = true;
- }
- else if (response.equalsIgnoreCase("UIDL")) {
- capabilities.uidl = true;
- }
- else if (response.equalsIgnoreCase("PIPELINING")) {
- capabilities.pipelining = true;
- }
- else if (response.equalsIgnoreCase("USER")) {
- capabilities.user = true;
- }
- else if (response.equalsIgnoreCase("TOP")) {
- capabilities.top = true;
- }
- }
- }
- catch (MessagingException me) {
- /*
- * The server may not support the CAPA command, so we just eat this Exception
- * and allow the empty capabilities object to be returned.
- */
- }
- return capabilities;
- }
-
- /**
- * Send a single command and wait for a single line response. Reopens the connection,
- * if it is closed. Leaves the connection open.
- *
- * @param command The command string to send to the server.
- * @return Returns the response string from the server.
- */
- private String executeSimpleCommand(String command) throws IOException, MessagingException {
- return executeSensitiveCommand(command, null);
- }
-
- /**
- * Send a single command and wait for a single line response. Reopens the connection,
- * if it is closed. Leaves the connection open.
- *
- * @param command The command string to send to the server.
- * @param sensitiveReplacement If the command includes sensitive data (e.g. authentication)
- * please pass a replacement string here (for logging).
- * @return Returns the response string from the server.
- */
- private String executeSensitiveCommand(String command, String sensitiveReplacement)
- throws IOException, MessagingException {
- open(OpenMode.READ_WRITE);
-
- if (command != null) {
- mTransport.writeLine(command, sensitiveReplacement);
- }
-
- String response = mTransport.readLine();
-
- if (response.length() > 1 && response.charAt(0) == '-') {
- throw new MessagingException(response);
- }
-
- return response;
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof Pop3Folder) {
- return ((Pop3Folder) o).mName.equals(mName);
- }
- return super.equals(o);
- }
-
- @Override
- // TODO this is deprecated, eventually discard
- public boolean isOpen() {
- return mTransport.isOpen();
- }
- }
-
- class Pop3Message extends MimeMessage {
- public Pop3Message(String uid, Pop3Folder folder) throws MessagingException {
- mUid = uid;
- mFolder = folder;
- mSize = -1;
- }
-
- public void setSize(int size) {
- mSize = size;
- }
-
- protected void parse(InputStream in) throws IOException, MessagingException {
- super.parse(in);
- }
-
- @Override
- public void setFlag(Flag flag, boolean set) throws MessagingException {
- super.setFlag(flag, set);
- mFolder.setFlags(new Message[] { this }, new Flag[] { flag }, set);
- }
- }
-
- /**
- * POP3 Capabilities as defined in RFC 2449. This is not a complete list of CAPA
- * responses - just those that we use in this client.
- */
- class Pop3Capabilities {
- /** The STLS (start TLS) command is supported */
- public boolean stls;
- /** the TOP command (retrieve a partial message) is supported */
- public boolean top;
- /** USER and PASS login/auth commands are supported */
- public boolean user;
- /** the optional UIDL command is supported (unused) */
- public boolean uidl;
- /** the server is capable of accepting multiple commands at a time (unused) */
- public boolean pipelining;
-
- public String toString() {
- return String.format("STLS %b, TOP %b, USER %b, UIDL %b, PIPELINING %b",
- stls,
- top,
- user,
- uidl,
- pipelining);
- }
- }
-
- // TODO figure out what is special about this and merge it into MailTransport
- class Pop3ResponseInputStream extends InputStream {
- InputStream mIn;
- boolean mStartOfLine = true;
- boolean mFinished;
-
- public Pop3ResponseInputStream(InputStream in) {
- mIn = in;
- }
-
- @Override
- public int read() throws IOException {
- if (mFinished) {
- return -1;
- }
- int d = mIn.read();
- if (mStartOfLine && d == '.') {
- d = mIn.read();
- if (d == '\r') {
- mFinished = true;
- mIn.read();
- return -1;
- }
- }
-
- mStartOfLine = (d == '\n');
-
- return d;
- }
- }
-}
diff --git a/src/com/android/email/mail/store/TrustManagerFactory.java b/src/com/android/email/mail/store/TrustManagerFactory.java
deleted file mode 100644
index 70cc322a0..000000000
--- a/src/com/android/email/mail/store/TrustManagerFactory.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.store;
-
-import android.util.Log;
-import android.net.http.DomainNameChecker;
-
-import java.security.KeyStore;
-import java.security.NoSuchAlgorithmException;
-import java.security.KeyStoreException;
-import java.security.cert.X509Certificate;
-import java.security.cert.CertificateException;
-
-import javax.net.ssl.X509TrustManager;
-import javax.net.ssl.TrustManager;
-
-public final class TrustManagerFactory {
- private static final String LOG_TAG = "TrustManagerFactory";
-
- private static X509TrustManager sSecureTrustManager;
- private static X509TrustManager sUnsecureTrustManager;
-
- private static class SimpleX509TrustManager implements X509TrustManager {
- public void checkClientTrusted(X509Certificate[] chain, String authType)
- throws CertificateException {
- }
-
- public void checkServerTrusted(X509Certificate[] chain, String authType)
- throws CertificateException {
- }
-
- public X509Certificate[] getAcceptedIssuers() {
- return null;
- }
- }
-
- private static class SecureX509TrustManager implements X509TrustManager {
- private X509TrustManager mTrustManager;
- private String mHost;
-
- SecureX509TrustManager(X509TrustManager trustManager, String host) {
- mTrustManager = trustManager;
- mHost = host;
- }
-
- public void checkClientTrusted(X509Certificate[] chain, String authType)
- throws CertificateException {
- mTrustManager.checkClientTrusted(chain, authType);
- }
-
- public void checkServerTrusted(X509Certificate[] chain, String authType)
- throws CertificateException {
-
- mTrustManager.checkServerTrusted(chain, authType);
-
- if (!DomainNameChecker.match(chain[0], mHost)) {
- throw new CertificateException("Certificate domain name does not match "
- + mHost);
- }
- }
-
- public X509Certificate[] getAcceptedIssuers() {
- return mTrustManager.getAcceptedIssuers();
- }
- }
-
- static {
- try {
- javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory.getInstance("X509");
- tmf.init((KeyStore) null);
- TrustManager[] tms = tmf.getTrustManagers();
- if (tms != null) {
- for (TrustManager tm : tms) {
- if (tm instanceof X509TrustManager) {
- sSecureTrustManager = (X509TrustManager) tm;
- break;
- }
- }
- }
- } catch (NoSuchAlgorithmException e) {
- Log.e(LOG_TAG, "Unable to get X509 Trust Manager ", e);
- } catch (KeyStoreException e) {
- Log.e(LOG_TAG, "Key Store exception while initializing TrustManagerFactory ", e);
- }
-
- sUnsecureTrustManager = new SimpleX509TrustManager();
- }
-
- private TrustManagerFactory() {
- }
-
- public static X509TrustManager get(String host, boolean secure) {
- return secure ? new SecureX509TrustManager(sSecureTrustManager, host) :
- sUnsecureTrustManager;
- }
-}
diff --git a/src/com/android/email/mail/transport/CountingOutputStream.java b/src/com/android/email/mail/transport/CountingOutputStream.java
deleted file mode 100644
index a5f10b5e4..000000000
--- a/src/com/android/email/mail/transport/CountingOutputStream.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.transport;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * A simple OutputStream that does nothing but count how many bytes are written to it and
- * makes that count available to callers.
- */
-public class CountingOutputStream extends OutputStream {
- private long mCount;
-
- public CountingOutputStream() {
- }
-
- public long getCount() {
- return mCount;
- }
-
- @Override
- public void write(int oneByte) throws IOException {
- mCount++;
- }
-}
diff --git a/src/com/android/email/mail/transport/EOLConvertingOutputStream.java b/src/com/android/email/mail/transport/EOLConvertingOutputStream.java
deleted file mode 100644
index d94ec1345..000000000
--- a/src/com/android/email/mail/transport/EOLConvertingOutputStream.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.transport;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class EOLConvertingOutputStream extends FilterOutputStream {
- int lastChar;
-
- public EOLConvertingOutputStream(OutputStream out) {
- super(out);
- }
-
- @Override
- public void write(int oneByte) throws IOException {
- if (oneByte == '\n') {
- if (lastChar != '\r') {
- super.write('\r');
- }
- }
- super.write(oneByte);
- lastChar = oneByte;
- }
-
- @Override
- public void flush() throws IOException {
- if (lastChar == '\r') {
- super.write('\n');
- lastChar = '\n';
- }
- super.flush();
- }
-}
diff --git a/src/com/android/email/mail/transport/MailTransport.java b/src/com/android/email/mail/transport/MailTransport.java
deleted file mode 100644
index 509d3d678..000000000
--- a/src/com/android/email/mail/transport/MailTransport.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.transport;
-
-import com.android.email.Email;
-import com.android.email.mail.CertificateValidationException;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Transport;
-import com.android.email.mail.store.TrustManagerFactory;
-
-import android.util.Config;
-import android.util.Log;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.net.SocketException;
-import java.net.URI;
-import java.security.GeneralSecurityException;
-import java.security.SecureRandom;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.TrustManager;
-
-/**
- * This class implements the common aspects of "transport", one layer below the
- * specific wire protocols such as POP3, IMAP, or SMTP.
- */
-public class MailTransport implements Transport {
-
- // TODO protected eventually
- /*protected*/ public static final int SOCKET_CONNECT_TIMEOUT = 10000;
- /*protected*/ public static final int SOCKET_READ_TIMEOUT = 60000;
-
- private String mDebugLabel;
-
- private String mHost;
- private int mPort;
- private String[] mUserInfoParts;
- private int mConnectionSecurity;
-
- private Socket mSocket;
- private InputStream mIn;
- private OutputStream mOut;
-
- /**
- * Simple constructor for starting from scratch. Call setUri() and setSecurity() to
- * complete the configuration.
- * @param debugLabel Label used for Log.d calls
- */
- public MailTransport(String debugLabel) {
- super();
- mDebugLabel = debugLabel;
- }
-
- /**
- * Get a new transport, using an existing one as a model. The new transport is configured as if
- * setUri() and setSecurity() have been called, but not opened or connected in any way.
- * @return a new Transport ready to open()
- */
- public Transport newInstanceWithConfiguration() {
- MailTransport newObject = new MailTransport(mDebugLabel);
-
- newObject.mDebugLabel = mDebugLabel;
- newObject.mHost = mHost;
- newObject.mPort = mPort;
- if (mUserInfoParts != null) {
- newObject.mUserInfoParts = mUserInfoParts.clone();
- }
- newObject.mConnectionSecurity = mConnectionSecurity;
- return newObject;
- }
-
- public void setUri(URI uri, int defaultPort) {
- mHost = uri.getHost();
-
- mPort = defaultPort;
- if (uri.getPort() != -1) {
- mPort = uri.getPort();
- }
-
- if (uri.getUserInfo() != null) {
- mUserInfoParts = uri.getUserInfo().split(":", 2);
- }
-
- }
-
- public String[] getUserInfoParts() {
- return mUserInfoParts;
- }
-
- public String getHost() {
- return mHost;
- }
-
- public int getPort() {
- return mPort;
- }
-
- public void setSecurity(int connectionSecurity) {
- mConnectionSecurity = connectionSecurity;
- }
-
- public int getSecurity() {
- return mConnectionSecurity;
- }
-
- public boolean canTrySslSecurity() {
- return (mConnectionSecurity == CONNECTION_SECURITY_SSL_REQUIRED
- || mConnectionSecurity == CONNECTION_SECURITY_SSL_OPTIONAL);
- }
-
- public boolean canTryTlsSecurity() {
- return (mConnectionSecurity == Transport.CONNECTION_SECURITY_TLS_OPTIONAL
- || mConnectionSecurity == Transport.CONNECTION_SECURITY_TLS_REQUIRED);
- }
-
- /**
- * Attempts to open a connection using the Uri supplied for connection parameters. Will attempt
- * an SSL connection if indicated.
- */
- public void open() throws MessagingException, CertificateValidationException {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, "*** " + mDebugLabel + " open " +
- getHost() + ":" + String.valueOf(getPort()));
- }
-
- try {
- SocketAddress socketAddress = new InetSocketAddress(getHost(), getPort());
- if (canTrySslSecurity()) {
- SSLContext sslContext = SSLContext.getInstance("TLS");
- final boolean secure = getSecurity() == Transport.CONNECTION_SECURITY_SSL_REQUIRED;
- sslContext.init(null, new TrustManager[] {
- TrustManagerFactory.get(getHost(), secure)
- }, new SecureRandom());
- mSocket = sslContext.getSocketFactory().createSocket();
- } else {
- mSocket = new Socket();
- }
- mSocket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
- mIn = new BufferedInputStream(mSocket.getInputStream(), 1024);
- mOut = new BufferedOutputStream(mSocket.getOutputStream(), 512);
-
- } catch (SSLException e) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, e.toString());
- }
- throw new CertificateValidationException(e.getMessage(), e);
- } catch (GeneralSecurityException gse) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, gse.toString());
- }
- throw new MessagingException(MessagingException.GENERAL_SECURITY, gse.toString());
- } catch (IOException ioe) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, ioe.toString());
- }
- throw new MessagingException(MessagingException.IOERROR, ioe.toString());
- }
- }
-
- /**
- * Attempts to reopen a TLS connection using the Uri supplied for connection parameters.
- *
- * TODO should we explicitly close the old socket? This seems funky to abandon it.
- */
- public void reopenTls() throws MessagingException {
- try {
- SSLContext sslContext = SSLContext.getInstance("TLS");
- boolean secure = getSecurity() == CONNECTION_SECURITY_TLS_REQUIRED;
- sslContext.init(null, new TrustManager[] {
- TrustManagerFactory.get(getHost(), secure)
- }, new SecureRandom());
- mSocket = sslContext.getSocketFactory().createSocket(mSocket, getHost(), getPort(),
- true);
- mSocket.setSoTimeout(SOCKET_READ_TIMEOUT);
- mIn = new BufferedInputStream(mSocket.getInputStream(), 1024);
- mOut = new BufferedOutputStream(mSocket.getOutputStream(), 512);
-
- } catch (GeneralSecurityException gse) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, gse.toString());
- }
- throw new MessagingException(MessagingException.GENERAL_SECURITY, gse.toString());
- } catch (IOException ioe) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, ioe.toString());
- }
- throw new MessagingException(MessagingException.IOERROR, ioe.toString());
- }
- }
-
- /**
- * Set the socket timeout.
- * @param timeoutMilliseconds the read timeout value if greater than {@code 0}, or
- * {@code 0} for an infinite timeout.
- */
- public void setSoTimeout(int timeoutMilliseconds) throws SocketException {
- mSocket.setSoTimeout(timeoutMilliseconds);
- }
-
- public boolean isOpen() {
- return (mIn != null && mOut != null &&
- mSocket != null && mSocket.isConnected() && !mSocket.isClosed());
- }
-
- /**
- * Close the connection. MUST NOT return any exceptions - must be "best effort" and safe.
- */
- public void close() {
- try {
- mIn.close();
- } catch (Exception e) {
- // May fail if the connection is already closed.
- }
- try {
- mOut.close();
- } catch (Exception e) {
- // May fail if the connection is already closed.
- }
- try {
- mSocket.close();
- } catch (Exception e) {
- // May fail if the connection is already closed.
- }
- mIn = null;
- mOut = null;
- mSocket = null;
- }
-
- public InputStream getInputStream() {
- return mIn;
- }
-
- public OutputStream getOutputStream() {
- return mOut;
- }
-
- /**
- * Writes a single line to the server using \r\n termination.
- */
- public void writeLine(String s, String sensitiveReplacement) throws IOException {
- if (Config.LOGD && Email.DEBUG) {
- if (sensitiveReplacement != null && !Email.DEBUG_SENSITIVE) {
- Log.d(Email.LOG_TAG, ">>> " + sensitiveReplacement);
- } else {
- Log.d(Email.LOG_TAG, ">>> " + s);
- }
- }
-
- OutputStream out = getOutputStream();
- out.write(s.getBytes());
- out.write('\r');
- out.write('\n');
- out.flush();
- }
-
- /**
- * Reads a single line from the server, using either \r\n or \n as the delimiter. The
- * delimiter char(s) are not included in the result.
- */
- public String readLine() throws IOException {
- StringBuffer sb = new StringBuffer();
- InputStream in = getInputStream();
- int d;
- while ((d = in.read()) != -1) {
- if (((char)d) == '\r') {
- continue;
- } else if (((char)d) == '\n') {
- break;
- } else {
- sb.append((char)d);
- }
- }
- if (d == -1 && Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, "End of stream reached while trying to read line.");
- }
- String ret = sb.toString();
- if (Config.LOGD) {
- if (Email.DEBUG) {
- Log.d(Email.LOG_TAG, "<<< " + ret);
- }
- }
- return ret;
- }
-
-
-}
diff --git a/src/com/android/email/mail/transport/SmtpSender.java b/src/com/android/email/mail/transport/SmtpSender.java
deleted file mode 100644
index 0b70d22d2..000000000
--- a/src/com/android/email/mail/transport/SmtpSender.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.transport;
-
-import com.android.email.Email;
-import com.android.email.codec.binary.Base64;
-import com.android.email.mail.Address;
-import com.android.email.mail.AuthenticationFailedException;
-import com.android.email.mail.CertificateValidationException;
-import com.android.email.mail.Message;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Sender;
-import com.android.email.mail.Transport;
-import com.android.email.mail.Message.RecipientType;
-
-import android.util.Config;
-import android.util.Log;
-
-import java.io.BufferedOutputStream;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.URI;
-import java.net.URISyntaxException;
-
-import javax.net.ssl.SSLException;
-
-/**
- * This class handles all of the protocol-level aspects of sending messages via SMTP.
- */
-public class SmtpSender extends Sender {
-
- public static final int CONNECTION_SECURITY_NONE = 0;
- public static final int CONNECTION_SECURITY_TLS_OPTIONAL = 1;
- public static final int CONNECTION_SECURITY_TLS_REQUIRED = 2;
- public static final int CONNECTION_SECURITY_SSL_REQUIRED = 3;
- public static final int CONNECTION_SECURITY_SSL_OPTIONAL = 4;
-
- private Transport mTransport;
- String mUsername;
- String mPassword;
-
- /**
- * Allowed formats for the Uri:
- * smtp://user:password@server:port CONNECTION_SECURITY_NONE
- * smtp+tls://user:password@server:port CONNECTION_SECURITY_TLS_OPTIONAL
- * smtp+tls+://user:password@server:port CONNECTION_SECURITY_TLS_REQUIRED
- * smtp+ssl+://user:password@server:port CONNECTION_SECURITY_SSL_REQUIRED
- * smtp+ssl://user:password@server:port CONNECTION_SECURITY_SSL_OPTIONAL
- *
- * @param uriString the Uri containing information to configure this sender
- */
- public SmtpSender(String uriString) throws MessagingException {
- URI uri;
- try {
- uri = new URI(uriString);
- } catch (URISyntaxException use) {
- throw new MessagingException("Invalid SmtpTransport URI", use);
- }
-
- String scheme = uri.getScheme();
- int connectionSecurity = Transport.CONNECTION_SECURITY_NONE;
- int defaultPort = -1;
- if (scheme.equals("smtp")) {
- connectionSecurity = CONNECTION_SECURITY_NONE;
- defaultPort = 25;
- } else if (scheme.equals("smtp+tls")) {
- connectionSecurity = CONNECTION_SECURITY_TLS_OPTIONAL;
- defaultPort = 25;
- } else if (scheme.equals("smtp+tls+")) {
- connectionSecurity = CONNECTION_SECURITY_TLS_REQUIRED;
- defaultPort = 25;
- } else if (scheme.equals("smtp+ssl+")) {
- connectionSecurity = CONNECTION_SECURITY_SSL_REQUIRED;
- defaultPort = 465;
- } else if (scheme.equals("smtp+ssl")) {
- connectionSecurity = CONNECTION_SECURITY_SSL_OPTIONAL;
- defaultPort = 465;
- } else {
- throw new MessagingException("Unsupported protocol");
- }
-
- mTransport = new MailTransport("SMTP");
- mTransport.setUri(uri, defaultPort);
- mTransport.setSecurity(connectionSecurity);
-
- String[] userInfoParts = mTransport.getUserInfoParts();
- if (userInfoParts != null) {
- mUsername = userInfoParts[0];
- if (userInfoParts.length > 1) {
- mPassword = userInfoParts[1];
- }
- }
- }
-
- /**
- * For testing only. Injects a different transport. The transport should already be set
- * up and ready to use. Do not use for real code.
- * @param testTransport The Transport to inject and use for all future communication.
- */
- /* package */ void setTransport(Transport testTransport) {
- mTransport = testTransport;
- }
-
- public void open() throws MessagingException {
- try {
- mTransport.open();
-
- // Eat the banner
- executeSimpleCommand(null);
-
- String localHost = "localhost";
- try {
- InetAddress localAddress = InetAddress.getLocalHost();
- localHost = localAddress.getHostName();
- } catch (Exception e) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, "Unable to look up localhost");
- }
- }
-
- String result = executeSimpleCommand("EHLO " + localHost);
-
- /*
- * TODO may need to add code to fall back to HELO I switched it from
- * using HELO on non STARTTLS connections because of AOL's mail
- * server. It won't let you use AUTH without EHLO.
- * We should really be paying more attention to the capabilities
- * and only attempting auth if it's available, and warning the user
- * if not.
- */
- if (mTransport.canTryTlsSecurity()) {
- if (result.contains("-STARTTLS")) {
- executeSimpleCommand("STARTTLS");
- mTransport.reopenTls();
- /*
- * Now resend the EHLO. Required by RFC2487 Sec. 5.2, and more specifically,
- * Exim.
- */
- result = executeSimpleCommand("EHLO " + localHost);
- } else if (mTransport.getSecurity() ==
- Transport.CONNECTION_SECURITY_TLS_REQUIRED) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, "TLS not supported but required");
- }
- throw new MessagingException(MessagingException.TLS_REQUIRED);
- }
- }
-
- /*
- * result contains the results of the EHLO in concatenated form
- */
- boolean authLoginSupported = result.matches(".*AUTH.*LOGIN.*$");
- boolean authPlainSupported = result.matches(".*AUTH.*PLAIN.*$");
-
- if (mUsername != null && mUsername.length() > 0 && mPassword != null
- && mPassword.length() > 0) {
- if (authPlainSupported) {
- saslAuthPlain(mUsername, mPassword);
- }
- else if (authLoginSupported) {
- saslAuthLogin(mUsername, mPassword);
- }
- else {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, "No valid authentication mechanism found.");
- }
- throw new MessagingException(MessagingException.AUTH_REQUIRED);
- }
- }
- } catch (SSLException e) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, e.toString());
- }
- throw new CertificateValidationException(e.getMessage(), e);
- } catch (IOException ioe) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, ioe.toString());
- }
- throw new MessagingException(MessagingException.IOERROR, ioe.toString());
- }
- }
-
- public void sendMessage(Message message) throws MessagingException {
- close();
- open();
- Address[] from = message.getFrom();
-
- try {
- executeSimpleCommand("MAIL FROM: " + "<" + from[0].getAddress() + ">");
- for (Address address : message.getRecipients(RecipientType.TO)) {
- executeSimpleCommand("RCPT TO: " + "<" + address.getAddress() + ">");
- }
- for (Address address : message.getRecipients(RecipientType.CC)) {
- executeSimpleCommand("RCPT TO: " + "<" + address.getAddress() + ">");
- }
- for (Address address : message.getRecipients(RecipientType.BCC)) {
- executeSimpleCommand("RCPT TO: " + "<" + address.getAddress() + ">");
- }
- message.setRecipients(RecipientType.BCC, null);
- executeSimpleCommand("DATA");
- // TODO byte stuffing
- // TODO most of the MIME writeTo functions layer on *additional* buffering
- // streams, making this one possibly not-necessary. Need to get to the bottom
- // of that.
- // TODO Also, need to be absolutely positively sure that flush() is called
- // on the wrappered outputs before sending the final \r\n via the regular mOut.
- message.writeTo(
- new EOLConvertingOutputStream(
- new BufferedOutputStream(mTransport.getOutputStream(), 1024)));
- executeSimpleCommand("\r\n.");
- } catch (IOException ioe) {
- throw new MessagingException("Unable to send message", ioe);
- }
- }
-
- /**
- * Close the protocol (and the transport below it).
- *
- * MUST NOT return any exceptions.
- */
- public void close() {
- mTransport.close();
- }
-
- /**
- * Send a single command and wait for a single response. Handles responses that continue
- * onto multiple lines. Throws MessagingException if response code is 4xx or 5xx. All traffic
- * is logged (if debug logging is enabled) so do not use this function for user ID or password.
- *
- * @param command The command string to send to the server.
- * @return Returns the response string from the server.
- */
- private String executeSimpleCommand(String command) throws IOException, MessagingException {
- return executeSensitiveCommand(command, null);
- }
-
- /**
- * Send a single command and wait for a single response. Handles responses that continue
- * onto multiple lines. Throws MessagingException if response code is 4xx or 5xx.
- *
- * @param command The command string to send to the server.
- * @param sensitiveReplacement If the command includes sensitive data (e.g. authentication)
- * please pass a replacement string here (for logging).
- * @return Returns the response string from the server.
- */
- private String executeSensitiveCommand(String command, String sensitiveReplacement)
- throws IOException, MessagingException {
- if (command != null) {
- mTransport.writeLine(command, sensitiveReplacement);
- }
-
- String line = mTransport.readLine();
-
- String result = line;
-
- while (line.length() >= 4 && line.charAt(3) == '-') {
- line = mTransport.readLine();
- result += line.substring(3);
- }
-
- char c = result.charAt(0);
- if ((c == '4') || (c == '5')) {
- throw new MessagingException(result);
- }
-
- return result;
- }
-
-
-// C: AUTH LOGIN
-// S: 334 VXNlcm5hbWU6
-// C: d2VsZG9u
-// S: 334 UGFzc3dvcmQ6
-// C: dzNsZDBu
-// S: 235 2.0.0 OK Authenticated
-//
-// Lines 2-5 of the conversation contain base64-encoded information. The same conversation, with base64 strings decoded, reads:
-//
-//
-// C: AUTH LOGIN
-// S: 334 Username:
-// C: weldon
-// S: 334 Password:
-// C: w3ld0n
-// S: 235 2.0.0 OK Authenticated
-
- private void saslAuthLogin(String username, String password) throws MessagingException,
- AuthenticationFailedException, IOException {
- try {
- executeSimpleCommand("AUTH LOGIN");
- executeSensitiveCommand(new String(Base64.encodeBase64(username.getBytes())),
- "/username redacted/");
- executeSensitiveCommand(new String(Base64.encodeBase64(password.getBytes())),
- "/password redacted/");
- }
- catch (MessagingException me) {
- if (me.getMessage().length() > 1 && me.getMessage().charAt(1) == '3') {
- throw new AuthenticationFailedException(me.getMessage());
- }
- throw me;
- }
- }
-
- private void saslAuthPlain(String username, String password) throws MessagingException,
- AuthenticationFailedException, IOException {
- byte[] data = ("\000" + username + "\000" + password).getBytes();
- data = new Base64().encode(data);
- try {
- executeSensitiveCommand("AUTH PLAIN " + new String(data), "AUTH PLAIN /redacted/");
- }
- catch (MessagingException me) {
- if (me.getMessage().length() > 1 && me.getMessage().charAt(1) == '3') {
- throw new AuthenticationFailedException(me.getMessage());
- }
- throw me;
- }
- }
-}
diff --git a/src/com/android/email/mail/transport/StatusOutputStream.java b/src/com/android/email/mail/transport/StatusOutputStream.java
deleted file mode 100644
index 83b077084..000000000
--- a/src/com/android/email/mail/transport/StatusOutputStream.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.transport;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import com.android.email.Email;
-
-import android.util.Config;
-import android.util.Log;
-
-public class StatusOutputStream extends FilterOutputStream {
- private long mCount = 0;
-
- public StatusOutputStream(OutputStream out) {
- super(out);
- }
-
- @Override
- public void write(int oneByte) throws IOException {
- super.write(oneByte);
- mCount++;
- if (Config.LOGV) {
- if (mCount % 1024 == 0) {
- Log.v(Email.LOG_TAG, "# " + mCount);
- }
- }
- }
-}
diff --git a/src/com/android/email/provider/AttachmentProvider.java b/src/com/android/email/provider/AttachmentProvider.java
deleted file mode 100644
index 7fa9be914..000000000
--- a/src/com/android/email/provider/AttachmentProvider.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.provider;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.net.Uri;
-import android.os.ParcelFileDescriptor;
-import android.provider.OpenableColumns;
-import android.util.Config;
-import android.util.Log;
-
-import com.android.email.Account;
-import com.android.email.Email;
-import com.android.email.Utility;
-import com.android.email.mail.internet.MimeUtility;
-
-/*
- * A simple ContentProvider that allows file access to Email's attachments.
- */
-public class AttachmentProvider extends ContentProvider {
- public static final Uri CONTENT_URI = Uri.parse( "content://com.android.email.attachmentprovider");
-
- private static final String FORMAT_RAW = "RAW";
- private static final String FORMAT_THUMBNAIL = "THUMBNAIL";
-
- public static class AttachmentProviderColumns {
- public static final String _ID = "_id";
- public static final String DATA = "_data";
- public static final String DISPLAY_NAME = "_display_name";
- public static final String SIZE = "_size";
- }
-
- public static Uri getAttachmentUri(Account account, long id) {
- return CONTENT_URI.buildUpon()
- .appendPath(account.getUuid() + ".db")
- .appendPath(Long.toString(id))
- .appendPath(FORMAT_RAW)
- .build();
- }
-
- public static Uri getAttachmentThumbnailUri(Account account, long id, int width, int height) {
- return CONTENT_URI.buildUpon()
- .appendPath(account.getUuid() + ".db")
- .appendPath(Long.toString(id))
- .appendPath(FORMAT_THUMBNAIL)
- .appendPath(Integer.toString(width))
- .appendPath(Integer.toString(height))
- .build();
- }
-
- public static Uri getAttachmentUri(String db, long id) {
- return CONTENT_URI.buildUpon()
- .appendPath(db)
- .appendPath(Long.toString(id))
- .appendPath(FORMAT_RAW)
- .build();
- }
-
- @Override
- public boolean onCreate() {
- /*
- * We use the cache dir as a temporary directory (since Android doesn't give us one) so
- * on startup we'll clean up any .tmp files from the last run.
- */
- File[] files = getContext().getCacheDir().listFiles();
- for (File file : files) {
- if (file.getName().endsWith(".tmp")) {
- file.delete();
- }
- }
- return true;
- }
-
- @Override
- public String getType(Uri uri) {
- List<String> segments = uri.getPathSegments();
- String dbName = segments.get(0);
- String id = segments.get(1);
- String format = segments.get(2);
- if (FORMAT_THUMBNAIL.equals(format)) {
- return "image/png";
- }
- else {
- String path = getContext().getDatabasePath(dbName).getAbsolutePath();
- SQLiteDatabase db = null;
- Cursor cursor = null;
- try {
- db = SQLiteDatabase.openDatabase(path, null, 0);
- cursor = db.query(
- "attachments",
- new String[] { "mime_type" },
- "id = ?",
- new String[] { id },
- null,
- null,
- null);
- cursor.moveToFirst();
- String type = cursor.getString(0);
- cursor.close();
- db.close();
- return type;
-
- }
- finally {
- if (cursor != null) {
- cursor.close();
- }
- if (db != null) {
- db.close();
- }
-
- }
- }
- }
-
- @Override
- public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
- List<String> segments = uri.getPathSegments();
- String dbName = segments.get(0);
- String id = segments.get(1);
- String format = segments.get(2);
- if (FORMAT_THUMBNAIL.equals(format)) {
- int width = Integer.parseInt(segments.get(3));
- int height = Integer.parseInt(segments.get(4));
- String filename = "thmb_" + dbName + "_" + id;
- File dir = getContext().getCacheDir();
- File file = new File(dir, filename);
- if (!file.exists()) {
- Uri attachmentUri = getAttachmentUri(dbName, Long.parseLong(id));
- String type = getType(attachmentUri);
- try {
- FileInputStream in = new FileInputStream(
- new File(getContext().getDatabasePath(dbName + "_att"), id));
- Bitmap thumbnail = createThumbnail(type, in);
- thumbnail = thumbnail.createScaledBitmap(thumbnail, width, height, true);
- FileOutputStream out = new FileOutputStream(file);
- thumbnail.compress(Bitmap.CompressFormat.PNG, 100, out);
- out.close();
- in.close();
- }
- catch (IOException ioe) {
- return null;
- }
- }
- return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
- }
- else {
- return ParcelFileDescriptor.open(
- new File(getContext().getDatabasePath(dbName + "_att"), id),
- ParcelFileDescriptor.MODE_READ_ONLY);
- }
- }
-
- @Override
- public int delete(Uri uri, String arg1, String[] arg2) {
- return 0;
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- return null;
- }
-
- @Override
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
- if (projection == null) {
- projection =
- new String[] {
- AttachmentProviderColumns._ID,
- AttachmentProviderColumns.DATA,
- };
- }
-
- List<String> segments = uri.getPathSegments();
- String dbName = segments.get(0);
- String id = segments.get(1);
- String format = segments.get(2);
- String path = getContext().getDatabasePath(dbName).getAbsolutePath();
- String name = null;
- int size = -1;
- SQLiteDatabase db = null;
- Cursor cursor = null;
- try {
- db = SQLiteDatabase.openDatabase(path, null, 0);
- cursor = db.query(
- "attachments",
- new String[] { "name", "size" },
- "id = ?",
- new String[] { id },
- null,
- null,
- null);
- if (!cursor.moveToFirst()) {
- return null;
- }
- name = cursor.getString(0);
- size = cursor.getInt(1);
- }
- finally {
- if (cursor != null) {
- cursor.close();
- }
- if (db != null) {
- db.close();
- }
- }
-
- MatrixCursor ret = new MatrixCursor(projection);
- Object[] values = new Object[projection.length];
- for (int i = 0, count = projection.length; i < count; i++) {
- String column = projection[i];
- if (AttachmentProviderColumns._ID.equals(column)) {
- values[i] = id;
- }
- else if (AttachmentProviderColumns.DATA.equals(column)) {
- values[i] = uri.toString();
- }
- else if (AttachmentProviderColumns.DISPLAY_NAME.equals(column)) {
- values[i] = name;
- }
- else if (AttachmentProviderColumns.SIZE.equals(column)) {
- values[i] = size;
- }
- }
- ret.addRow(values);
- return ret;
- }
-
- @Override
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- return 0;
- }
-
- private Bitmap createThumbnail(String type, InputStream data) {
- if(MimeUtility.mimeTypeMatches(type, "image/*")) {
- return createImageThumbnail(data);
- }
- return null;
- }
-
- private Bitmap createImageThumbnail(InputStream data) {
- try {
- Bitmap bitmap = BitmapFactory.decodeStream(data);
- return bitmap;
- }
- catch (OutOfMemoryError oome) {
- /*
- * Improperly downloaded images, corrupt bitmaps and the like can commonly
- * cause OOME due to invalid allocation sizes. We're happy with a null bitmap in
- * that case. If the system is really out of memory we'll know about it soon
- * enough.
- */
- return null;
- }
- catch (Exception e) {
- return null;
- }
- }
-}
diff --git a/src/com/android/email/service/BootReceiver.java b/src/com/android/email/service/BootReceiver.java
deleted file mode 100644
index e246ded3c..000000000
--- a/src/com/android/email/service/BootReceiver.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.service;
-
-import com.android.email.MessagingController;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-public class BootReceiver extends BroadcastReceiver {
- public void onReceive(Context context, Intent intent) {
- if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
- MailService.actionReschedule(context);
- }
- else if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(intent.getAction())) {
- MailService.actionCancel(context);
- }
- else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(intent.getAction())) {
- MailService.actionReschedule(context);
- }
- }
-}
diff --git a/src/com/android/email/service/MailService.java b/src/com/android/email/service/MailService.java
deleted file mode 100644
index 27e3cfd05..000000000
--- a/src/com/android/email/service/MailService.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.service;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import android.app.AlarmManager;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.IBinder;
-import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.Config;
-import android.util.Log;
-
-import com.android.email.Account;
-import com.android.email.Email;
-import com.android.email.MessagingController;
-import com.android.email.MessagingListener;
-import com.android.email.Preferences;
-import com.android.email.R;
-import com.android.email.activity.Accounts;
-import com.android.email.activity.FolderMessageList;
-
-/**
- */
-public class MailService extends Service {
- private static final String ACTION_CHECK_MAIL = "com.android.email.intent.action.MAIL_SERVICE_WAKEUP";
- private static final String ACTION_RESCHEDULE = "com.android.email.intent.action.MAIL_SERVICE_RESCHEDULE";
- private static final String ACTION_CANCEL = "com.android.email.intent.action.MAIL_SERVICE_CANCEL";
-
- private Listener mListener = new Listener();
-
- private int mStartId;
-
- public static void actionReschedule(Context context) {
- Intent i = new Intent();
- i.setClass(context, MailService.class);
- i.setAction(MailService.ACTION_RESCHEDULE);
- context.startService(i);
- }
-
- public static void actionCancel(Context context) {
- Intent i = new Intent();
- i.setClass(context, MailService.class);
- i.setAction(MailService.ACTION_CANCEL);
- context.startService(i);
- }
-
- @Override
- public void onStart(Intent intent, int startId) {
- super.onStart(intent, startId);
- this.mStartId = startId;
-
- MessagingController controller = MessagingController.getInstance(getApplication());
- controller.addListener(mListener);
- if (ACTION_CHECK_MAIL.equals(intent.getAction())) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, "*** MailService: checking mail");
- }
- // Only check mail for accounts that have enabled automatic checking. There is still
- // a bug here in that we check every enabled account, on every refresh - irrespective
- // of that account's refresh frequency - but this fixes the worst case of checking
- // accounts that should not have been checked at all.
- // Also note: Due to the organization of this service, you must gather the accounts
- // and make a single call to controller.checkMail().
- ArrayList<Account> accountsToCheck = new ArrayList<Account>();
- for (Account account : Preferences.getPreferences(this).getAccounts()) {
- if (account.getAutomaticCheckIntervalMinutes() != -1) {
- accountsToCheck.add(account);
- }
- }
- Account[] accounts = accountsToCheck.toArray(new Account[accountsToCheck.size()]);
- controller.checkMail(this, accounts, mListener);
- }
- else if (ACTION_CANCEL.equals(intent.getAction())) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, "*** MailService: cancel");
- }
- cancel();
- stopSelf(startId);
- }
- else if (ACTION_RESCHEDULE.equals(intent.getAction())) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, "*** MailService: reschedule");
- }
- reschedule();
- stopSelf(startId);
- }
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- MessagingController.getInstance(getApplication()).removeListener(mListener);
- }
-
- private void cancel() {
- AlarmManager alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
- Intent i = new Intent();
- i.setClassName("com.android.email", "com.android.email.service.MailService");
- i.setAction(ACTION_CHECK_MAIL);
- PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
- alarmMgr.cancel(pi);
- }
-
- private void reschedule() {
- AlarmManager alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
- Intent i = new Intent();
- i.setClassName("com.android.email", "com.android.email.service.MailService");
- i.setAction(ACTION_CHECK_MAIL);
- PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
-
- int shortestInterval = -1;
- for (Account account : Preferences.getPreferences(this).getAccounts()) {
- if (account.getAutomaticCheckIntervalMinutes() != -1
- && (account.getAutomaticCheckIntervalMinutes() < shortestInterval || shortestInterval == -1)) {
- shortestInterval = account.getAutomaticCheckIntervalMinutes();
- }
- }
-
- if (shortestInterval == -1) {
- alarmMgr.cancel(pi);
- }
- else {
- alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()
- + (shortestInterval * (60 * 1000)), pi);
- }
- }
-
- public IBinder onBind(Intent intent) {
- return null;
- }
-
- class Listener extends MessagingListener {
- HashMap<Account, Integer> accountsWithNewMail = new HashMap<Account, Integer>();
-
- // TODO this should be redone because account is usually null, not very interesting.
- // I think it would make more sense to pass Account[] here in case anyone uses it
- // In any case, it should be noticed that this is called once per cycle
- @Override
- public void checkMailStarted(Context context, Account account) {
- accountsWithNewMail.clear();
- }
-
- // Called once per checked account
- @Override
- public void checkMailFailed(Context context, Account account, String reason) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, "*** MailService: checkMailFailed: " + reason);
- }
- reschedule();
- stopSelf(mStartId);
- }
-
- // Called once per checked account
- @Override
- public void synchronizeMailboxFinished(
- Account account,
- String folder,
- int totalMessagesInMailbox,
- int numNewMessages) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, "*** MailService: synchronizeMailboxFinished: total=" +
- totalMessagesInMailbox + " new=" + numNewMessages);
- }
- if (account.isNotifyNewMail() && numNewMessages > 0) {
- accountsWithNewMail.put(account, numNewMessages);
- }
- }
-
- // TODO this should be redone because account is usually null, not very interesting.
- // I think it would make more sense to pass Account[] here in case anyone uses it
- // In any case, it should be noticed that this is called once per cycle
- @Override
- public void checkMailFinished(Context context, Account account) {
- if (Config.LOGD && Email.DEBUG) {
- Log.d(Email.LOG_TAG, "*** MailService: checkMailFinished");
- }
- NotificationManager notifMgr = (NotificationManager)context
- .getSystemService(Context.NOTIFICATION_SERVICE);
-
- if (accountsWithNewMail.size() > 0) {
- Notification notif = new Notification(R.drawable.stat_notify_email_generic,
- getString(R.string.notification_new_title), System.currentTimeMillis());
- boolean vibrate = false;
- String ringtone = null;
- if (accountsWithNewMail.size() > 1) {
- for (Account account1 : accountsWithNewMail.keySet()) {
- if (account1.isVibrate()) vibrate = true;
- ringtone = account1.getRingtone();
- }
- Intent i = new Intent(context, Accounts.class);
- PendingIntent pi = PendingIntent.getActivity(context, 0, i, 0);
- notif.setLatestEventInfo(context, getString(R.string.notification_new_title),
- getString(R.string.notification_new_multi_account_fmt,
- accountsWithNewMail.size()), pi);
- } else {
- Account account1 = accountsWithNewMail.keySet().iterator().next();
- int totalNewMails = accountsWithNewMail.get(account1);
- Intent i = FolderMessageList.actionHandleAccountIntent(context, account1, Email.INBOX);
- PendingIntent pi = PendingIntent.getActivity(context, 0, i, 0);
- notif.setLatestEventInfo(context, getString(R.string.notification_new_title),
- getString(R.string.notification_new_one_account_fmt, totalNewMails,
- account1.getDescription()), pi);
- vibrate = account1.isVibrate();
- ringtone = account1.getRingtone();
- }
- notif.defaults = Notification.DEFAULT_LIGHTS;
- notif.sound = TextUtils.isEmpty(ringtone) ? null : Uri.parse(ringtone);
- if (vibrate) {
- notif.defaults |= Notification.DEFAULT_VIBRATE;
- }
- notifMgr.notify(1, notif);
- }
-
- reschedule();
- stopSelf(mStartId);
- }
- }
-}
diff --git a/src/com/beetstra/jutf7/Base64Util.java b/src/com/beetstra/jutf7/Base64Util.java
deleted file mode 100644
index 6dffb32c5..000000000
--- a/src/com/beetstra/jutf7/Base64Util.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/* ====================================================================
- * Copyright (c) 2006 J.T. Beetstra
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * ====================================================================
- */
-
-package com.beetstra.jutf7;
-
-import java.util.Arrays;
-
-/**
- * <p>
- * Represent a base 64 mapping. The 64 characters used in the encoding can be
- * specified, since modified-UTF-7 uses other characters than UTF-7 (',' instead
- * of '/').
- * </p>
- * <p>
- * The exact type of the arguments and result values is adapted to the needs of
- * the encoder and decoder, as opposed to following a strict interpretation of
- * base 64.
- * </p>
- * <p>
- * Base 64, as specified in RFC 2045, is an encoding used to encode bytes as
- * characters. In (modified-)UTF-7 however, it is used to encode characters as
- * bytes, using some intermediate steps:
- * </p>
- * <ol>
- * <li>Encode all characters as a 16-bit (UTF-16) integer value</li>
- * <li>Write this as stream of bytes (most-significant first)</li>
- * <li>Encode these bytes using (modified) base 64 encoding</li>
- * <li>Write the thus formed stream of characters as a stream of bytes, using
- * ASCII encoding</li>
- * </ol>
- *
- * @author Jaap Beetstra
- */
-class Base64Util {
- private static final int ALPHABET_LENGTH = 64;
- private final char[] alphabet;
- private final int[] inverseAlphabet;
-
- /**
- * Initializes the class with the specified encoding/decoding alphabet.
- *
- * @param alphabet
- * @throws IllegalArgumentException if alphabet is not 64 characters long or
- * contains characters which are not 7-bit ASCII
- */
- Base64Util(final String alphabet) {
- this.alphabet = alphabet.toCharArray();
- if (alphabet.length() != ALPHABET_LENGTH)
- throw new IllegalArgumentException("alphabet has incorrect length (should be 64, not "
- + alphabet.length() + ")");
- inverseAlphabet = new int[128];
- Arrays.fill(inverseAlphabet, -1);
- for (int i = 0; i < this.alphabet.length; i++) {
- final char ch = this.alphabet[i];
- if (ch >= 128)
- throw new IllegalArgumentException("invalid character in alphabet: " + ch);
- inverseAlphabet[ch] = i;
- }
- }
-
- /**
- * Returns the integer value of the six bits represented by the specified
- * character.
- *
- * @param ch The character, as a ASCII encoded byte
- * @return The six bits, as an integer value, or -1 if the byte is not in
- * the alphabet
- */
- int getSextet(final byte ch) {
- if (ch >= 128)
- return -1;
- return inverseAlphabet[ch];
- }
-
- /**
- * Tells whether the alphabet contains the specified character.
- *
- * @param ch The character
- * @return true if the alphabet contains <code>ch</code>, false otherwise
- */
- boolean contains(final char ch) {
- if (ch >= 128)
- return false;
- return inverseAlphabet[ch] >= 0;
- }
-
- /**
- * Encodes the six bit group as a character.
- *
- * @param sextet The six bit group to be encoded
- * @return The ASCII value of the character
- */
- byte getChar(final int sextet) {
- return (byte)alphabet[sextet];
- }
-}
diff --git a/src/com/beetstra/jutf7/CharsetProvider.java b/src/com/beetstra/jutf7/CharsetProvider.java
deleted file mode 100644
index f0cabe562..000000000
--- a/src/com/beetstra/jutf7/CharsetProvider.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/* ====================================================================
- * Copyright (c) 2006 J.T. Beetstra
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * ====================================================================
- */
-
-package com.beetstra.jutf7;
-
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * <p>
- * Charset service-provider class used for both variants of the UTF-7 charset
- * and the modified-UTF-7 charset.
- * </p>
- *
- * @author Jaap Beetstra
- */
-public class CharsetProvider extends java.nio.charset.spi.CharsetProvider {
- private static final String UTF7_NAME = "UTF-7";
- private static final String UTF7_O_NAME = "X-UTF-7-OPTIONAL";
- private static final String UTF7_M_NAME = "X-MODIFIED-UTF-7";
- private static final String[] UTF7_ALIASES = new String[] {
- "UNICODE-1-1-UTF-7", "CSUNICODE11UTF7", "X-RFC2152", "X-RFC-2152"
- };
- private static final String[] UTF7_O_ALIASES = new String[] {
- "X-RFC2152-OPTIONAL", "X-RFC-2152-OPTIONAL"
- };
- private static final String[] UTF7_M_ALIASES = new String[] {
- "X-IMAP-MODIFIED-UTF-7", "X-IMAP4-MODIFIED-UTF7", "X-IMAP4-MODIFIED-UTF-7",
- "X-RFC3501", "X-RFC-3501"
- };
- private Charset utf7charset = new UTF7Charset(UTF7_NAME, UTF7_ALIASES, false);
- private Charset utf7oCharset = new UTF7Charset(UTF7_O_NAME, UTF7_O_ALIASES, true);
- private Charset imap4charset = new ModifiedUTF7Charset(UTF7_M_NAME, UTF7_M_ALIASES);
- private List charsets;
-
- public CharsetProvider() {
- charsets = Arrays.asList(new Object[] {
- utf7charset, imap4charset, utf7oCharset
- });
- }
-
- /**
- * {@inheritDoc}
- */
- public Charset charsetForName(String charsetName) {
- charsetName = charsetName.toUpperCase();
- for (Iterator iter = charsets.iterator(); iter.hasNext();) {
- Charset charset = (Charset)iter.next();
- if (charset.name().equals(charsetName))
- return charset;
- }
- for (Iterator iter = charsets.iterator(); iter.hasNext();) {
- Charset charset = (Charset)iter.next();
- if (charset.aliases().contains(charsetName))
- return charset;
- }
- return null;
- }
-
- /**
- * {@inheritDoc}
- */
- public Iterator charsets() {
- return charsets.iterator();
- }
-}
diff --git a/src/com/beetstra/jutf7/ModifiedUTF7Charset.java b/src/com/beetstra/jutf7/ModifiedUTF7Charset.java
deleted file mode 100644
index 603a19ee9..000000000
--- a/src/com/beetstra/jutf7/ModifiedUTF7Charset.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/* ====================================================================
- * Copyright (c) 2006 J.T. Beetstra
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * ====================================================================
- */
-
-package com.beetstra.jutf7;
-
-/**
- * <p>
- * The character set specified in RFC 3501 to use for IMAP4rev1 mailbox name
- * encoding.
- * </p>
- *
- * @see <a href="http://tools.ietf.org/html/rfc3501">RFC 3501< /a>
- * @author Jaap Beetstra
- */
-class ModifiedUTF7Charset extends UTF7StyleCharset {
- private static final String MODIFIED_BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- + "abcdefghijklmnopqrstuvwxyz" + "0123456789+,";
-
- ModifiedUTF7Charset(String name, String[] aliases) {
- super(name, aliases, MODIFIED_BASE64_ALPHABET, true);
- }
-
- boolean canEncodeDirectly(char ch) {
- if (ch == shift())
- return false;
- return ch >= 0x20 && ch <= 0x7E;
- }
-
- byte shift() {
- return '&';
- }
-
- byte unshift() {
- return '-';
- }
-}
diff --git a/src/com/beetstra/jutf7/UTF7Charset.java b/src/com/beetstra/jutf7/UTF7Charset.java
deleted file mode 100644
index 8c85472cf..000000000
--- a/src/com/beetstra/jutf7/UTF7Charset.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/* ====================================================================
- * Copyright (c) 2006 J.T. Beetstra
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * ====================================================================
- */
-
-package com.beetstra.jutf7;
-
-/**
- * <p>
- * The character set specified in RFC 2152. Two variants are supported using the
- * encodeOptional constructor flag
- * </p>
- *
- * @see <a href="http://tools.ietf.org/html/rfc2152">RFC 2152< /a>
- * @author Jaap Beetstra
- */
-class UTF7Charset extends UTF7StyleCharset {
- private static final String BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/";
- private static final String SET_D = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'(),-./:?";
- private static final String SET_O = "!\"#$%&*;<=>@[]^_`{|}";
- private static final String RULE_3 = " \t\r\n";
- final String directlyEncoded;
-
- UTF7Charset(String name, String[] aliases, boolean includeOptional) {
- super(name, aliases, BASE64_ALPHABET, false);
- if (includeOptional)
- this.directlyEncoded = SET_D + SET_O + RULE_3;
- else
- this.directlyEncoded = SET_D + RULE_3;
- }
-
- /*
- * (non-Javadoc)
- * @see com.beetstra.jutf7.UTF7StyleCharset#canEncodeDirectly(char)
- */
- boolean canEncodeDirectly(char ch) {
- return directlyEncoded.indexOf(ch) >= 0;
- }
-
- /*
- * (non-Javadoc)
- * @see com.beetstra.jutf7.UTF7StyleCharset#shift()
- */
- byte shift() {
- return '+';
- }
-
- /*
- * (non-Javadoc)
- * @see com.beetstra.jutf7.UTF7StyleCharset#unshift()
- */
- byte unshift() {
- return '-';
- }
-}
diff --git a/src/com/beetstra/jutf7/UTF7StyleCharset.java b/src/com/beetstra/jutf7/UTF7StyleCharset.java
deleted file mode 100644
index 0878af603..000000000
--- a/src/com/beetstra/jutf7/UTF7StyleCharset.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/* ====================================================================
- * Copyright (c) 2006 J.T. Beetstra
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * ====================================================================
- */
-
-package com.beetstra.jutf7;
-
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CharsetEncoder;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * <p>
- * Abstract base class for UTF-7 style encoding and decoding.
- * </p>
- *
- * @author Jaap Beetstra
- */
-abstract class UTF7StyleCharset extends Charset {
- private static final List CONTAINED = Arrays.asList(new String[] {
- "US-ASCII", "ISO-8859-1", "UTF-8", "UTF-16", "UTF-16LE", "UTF-16BE"
- });
- final boolean strict;
- Base64Util base64;
-
- /**
- * <p>
- * Besides the name and aliases, two additional parameters are required.
- * First the base 64 alphabet used; in modified UTF-7 a slightly different
- * alphabet is used. Additionally, it should be specified if encoders and
- * decoders should be strict about the interpretation of malformed encoded
- * sequences. This is used since modified UTF-7 specifically disallows some
- * constructs which are allowed (or not specifically disallowed) in UTF-7
- * (RFC 2152).
- * </p>
- *
- * @param canonicalName The name as defined in java.nio.charset.Charset
- * @param aliases The aliases as defined in java.nio.charset.Charset
- * @param alphabet The base 64 alphabet used
- * @param strict True if strict handling of sequences is requested
- */
- protected UTF7StyleCharset(String canonicalName, String[] aliases, String alphabet,
- boolean strict) {
- super(canonicalName, aliases);
- this.base64 = new Base64Util(alphabet);
- this.strict = strict;
- }
-
- /*
- * (non-Javadoc)
- * @see java.nio.charset.Charset#contains(java.nio.charset.Charset)
- */
- public boolean contains(final Charset cs) {
- return CONTAINED.contains(cs.name());
- }
-
- /*
- * (non-Javadoc)
- * @see java.nio.charset.Charset#newDecoder()
- */
- public CharsetDecoder newDecoder() {
- return new UTF7StyleCharsetDecoder(this, base64, strict);
- }
-
- /*
- * (non-Javadoc)
- * @see java.nio.charset.Charset#newEncoder()
- */
- public CharsetEncoder newEncoder() {
- return new UTF7StyleCharsetEncoder(this, base64, strict);
- }
-
- /**
- * Tells if a character can be encoded using simple (US-ASCII) encoding or
- * requires base 64 encoding.
- *
- * @param ch The character
- * @return True if the character can be encoded directly, false otherwise
- */
- abstract boolean canEncodeDirectly(char ch);
-
- /**
- * Returns character used to switch to base 64 encoding.
- *
- * @return The shift character
- */
- abstract byte shift();
-
- /**
- * Returns character used to switch from base 64 encoding to simple
- * encoding.
- *
- * @return The unshift character
- */
- abstract byte unshift();
-}
diff --git a/src/com/beetstra/jutf7/UTF7StyleCharsetDecoder.java b/src/com/beetstra/jutf7/UTF7StyleCharsetDecoder.java
deleted file mode 100644
index 2fa9d3435..000000000
--- a/src/com/beetstra/jutf7/UTF7StyleCharsetDecoder.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/* ====================================================================
- * Copyright (c) 2006 J.T. Beetstra
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * ====================================================================
- */
-
-package com.beetstra.jutf7;
-
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CoderResult;
-
-/**
- * <p>
- * The CharsetDecoder used to decode both variants of the UTF-7 charset and the
- * modified-UTF-7 charset.
- * </p>
- *
- * @author Jaap Beetstra
- */
-class UTF7StyleCharsetDecoder extends CharsetDecoder {
- private final Base64Util base64;
- private final byte shift;
- private final byte unshift;
- private final boolean strict;
- private boolean base64mode;
- private int bitsRead;
- private int tempChar;
- private boolean justShifted;
- private boolean justUnshifted;
-
- UTF7StyleCharsetDecoder(UTF7StyleCharset cs, Base64Util base64, boolean strict) {
- super(cs, 0.6f, 1.0f);
- this.base64 = base64;
- this.strict = strict;
- this.shift = cs.shift();
- this.unshift = cs.unshift();
- }
-
- /*
- * (non-Javadoc)
- * @see java.nio.charset.CharsetDecoder#decodeLoop(java.nio.ByteBuffer,
- * java.nio.CharBuffer)
- */
- protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
- while (in.hasRemaining()) {
- byte b = in.get();
- if (base64mode) {
- if (b == unshift) {
- if (base64bitsWaiting())
- return malformed(in);
- if (justShifted) {
- if (!out.hasRemaining())
- return overflow(in);
- out.put((char)shift);
- } else
- justUnshifted = true;
- setUnshifted();
- } else {
- if (!out.hasRemaining())
- return overflow(in);
- CoderResult result = handleBase64(in, out, b);
- if (result != null)
- return result;
- }
- justShifted = false;
- } else {
- if (b == shift) {
- base64mode = true;
- if (justUnshifted && strict)
- return malformed(in);
- justShifted = true;
- continue;
- }
- if (!out.hasRemaining())
- return overflow(in);
- out.put((char)b);
- justUnshifted = false;
- }
- }
- return CoderResult.UNDERFLOW;
- }
-
- private CoderResult overflow(ByteBuffer in) {
- in.position(in.position() - 1);
- return CoderResult.OVERFLOW;
- }
-
- /**
- * <p>
- * Decodes a byte in <i>base 64 mode</i>. Will directly write a character to
- * the output buffer if completed.
- * </p>
- *
- * @param in The input buffer
- * @param out The output buffer
- * @param lastRead Last byte read from the input buffer
- * @return CoderResult.malformed if a non-base 64 character was encountered
- * in strict mode, null otherwise
- */
- private CoderResult handleBase64(ByteBuffer in, CharBuffer out, byte lastRead) {
- CoderResult result = null;
- int sextet = base64.getSextet(lastRead);
- if (sextet >= 0) {
- bitsRead += 6;
- if (bitsRead < 16) {
- tempChar += sextet << (16 - bitsRead);
- } else {
- bitsRead -= 16;
- tempChar += sextet >> (bitsRead);
- out.put((char)tempChar);
- tempChar = (sextet << (16 - bitsRead)) & 0xFFFF;
- }
- } else {
- if (strict)
- return malformed(in);
- out.put((char)lastRead);
- if (base64bitsWaiting())
- result = malformed(in);
- setUnshifted();
- }
- return result;
- }
-
- /*
- * (non-Javadoc)
- * @see java.nio.charset.CharsetDecoder#implFlush(java.nio.CharBuffer)
- */
- protected CoderResult implFlush(CharBuffer out) {
- if ((base64mode && strict) || base64bitsWaiting())
- return CoderResult.malformedForLength(1);
- return CoderResult.UNDERFLOW;
- }
-
- /*
- * (non-Javadoc)
- * @see java.nio.charset.CharsetDecoder#implReset()
- */
- protected void implReset() {
- setUnshifted();
- justUnshifted = false;
- }
-
- /**
- * <p>
- * Resets the input buffer position to just before the last byte read, and
- * returns a result indicating to skip the last byte.
- * </p>
- *
- * @param in The input buffer
- * @return CoderResult.malformedForLength(1);
- */
- private CoderResult malformed(ByteBuffer in) {
- in.position(in.position() - 1);
- return CoderResult.malformedForLength(1);
- }
-
- /**
- * @return True if there are base64 encoded characters waiting to be written
- */
- private boolean base64bitsWaiting() {
- return tempChar != 0 || bitsRead >= 6;
- }
-
- /**
- * <p>
- * Updates internal state to reflect the decoder is no longer in <i>base 64
- * mode</i>
- * </p>
- */
- private void setUnshifted() {
- base64mode = false;
- bitsRead = 0;
- tempChar = 0;
- }
-}
diff --git a/src/com/beetstra/jutf7/UTF7StyleCharsetEncoder.java b/src/com/beetstra/jutf7/UTF7StyleCharsetEncoder.java
deleted file mode 100644
index de8239713..000000000
--- a/src/com/beetstra/jutf7/UTF7StyleCharsetEncoder.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/* ====================================================================
- * Copyright (c) 2006 J.T. Beetstra
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * ====================================================================
- */
-
-package com.beetstra.jutf7;
-
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CoderResult;
-
-/**
- * <p>
- * The CharsetEncoder used to encode both variants of the UTF-7 charset and the
- * modified-UTF-7 charset.
- * </p>
- * <p>
- * <strong>Please note this class does not behave strictly according to the
- * specification in Sun Java VMs before 1.6.</strong> This is done to get around
- * a bug in the implementation of
- * {@link java.nio.charset.CharsetEncoder#encode(CharBuffer)}. Unfortunately,
- * that method cannot be overridden.
- * </p>
- *
- * @see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6221056">JDK
- * bug 6221056< /a>
- * @author Jaap Beetstra
- */
-class UTF7StyleCharsetEncoder extends CharsetEncoder {
- private static final float AVG_BYTES_PER_CHAR = 1.5f;
- private static final float MAX_BYTES_PER_CHAR = 5.0f;
- private final UTF7StyleCharset cs;
- private final Base64Util base64;
- private final byte shift;
- private final byte unshift;
- private final boolean strict;
- private boolean base64mode;
- private int bitsToOutput;
- private int sextet;
- static boolean useUglyHackToForceCallToFlushInJava5;
- static {
- String version = System.getProperty("java.specification.version");
- String vendor = System.getProperty("java.vm.vendor");
- useUglyHackToForceCallToFlushInJava5 = "1.4".equals(version) || "1.5".equals(version);
- useUglyHackToForceCallToFlushInJava5 &= "Sun Microsystems Inc.".equals(vendor);
- }
-
- UTF7StyleCharsetEncoder(UTF7StyleCharset cs, Base64Util base64, boolean strict) {
- super(cs, AVG_BYTES_PER_CHAR, MAX_BYTES_PER_CHAR);
- this.cs = cs;
- this.base64 = base64;
- this.strict = strict;
- this.shift = cs.shift();
- this.unshift = cs.unshift();
- }
-
- /*
- * (non-Javadoc)
- * @see java.nio.charset.CharsetEncoder#implReset()
- */
- protected void implReset() {
- base64mode = false;
- sextet = 0;
- bitsToOutput = 0;
- }
-
- /**
- * {@inheritDoc}
- * <p>
- * Note that this method might return <code>CoderResult.OVERFLOW</code> (as
- * is required by the specification) if insufficient space is available in
- * the output buffer. However, calling it again on JDKs before Java 6
- * triggers a bug in
- * {@link java.nio.charset.CharsetEncoder#flush(ByteBuffer)} causing it to
- * throw an IllegalStateException (the buggy method is <code>final</code>,
- * thus cannot be overridden).
- * </p>
- *
- * @see <a
- * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6227608">
- * JDK bug 6227608< /a>
- * @param out The output byte buffer
- * @return A coder-result object describing the reason for termination
- */
- protected CoderResult implFlush(ByteBuffer out) {
- if (base64mode) {
- if (out.remaining() < 2)
- return CoderResult.OVERFLOW;
- if (bitsToOutput != 0)
- out.put(base64.getChar(sextet));
- out.put(unshift);
- }
- return CoderResult.UNDERFLOW;
- }
-
- /**
- * {@inheritDoc}
- * <p>
- * Note that this method might return <code>CoderResult.OVERFLOW</code>,
- * even though there is sufficient space available in the output buffer.
- * This is done to force the broken implementation of
- * {@link java.nio.charset.CharsetEncoder#encode(CharBuffer)} to call flush
- * (the buggy method is <code>final</code>, thus cannot be overridden).
- * </p>
- * <p>
- * However, String.getBytes() fails if CoderResult.OVERFLOW is returned,
- * since this assumes it always allocates sufficient bytes (maxBytesPerChar
- * * nr_of_chars). Thus, as an extra check, the size of the input buffer is
- * compared against the size of the output buffer. A static variable is used
- * to indicate if a broken java version is used.
- * </p>
- * <p>
- * It is not possible to directly write the last few bytes, since more bytes
- * might be waiting to be encoded then those available in the input buffer.
- * </p>
- *
- * @see <a
- * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6221056">
- * JDK bug 6221056< /a>
- * @param in The input character buffer
- * @param out The output byte buffer
- * @return A coder-result object describing the reason for termination
- */
- protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
- while (in.hasRemaining()) {
- if (out.remaining() < 4)
- return CoderResult.OVERFLOW;
- char ch = in.get();
- if (cs.canEncodeDirectly(ch)) {
- unshift(out, ch);
- out.put((byte)ch);
- } else if (!base64mode && ch == shift) {
- out.put(shift);
- out.put(unshift);
- } else
- encodeBase64(ch, out);
- }
- /*
- * <HACK type="ugly"> These lines are required to trick JDK 1.5 and
- * earlier into flushing when using Charset.encode(String),
- * Charset.encode(CharBuffer) or CharsetEncoder.encode(CharBuffer)
- * Without them, the last few bytes may be missing.
- */
- if (base64mode && useUglyHackToForceCallToFlushInJava5
- && out.limit() != MAX_BYTES_PER_CHAR * in.limit())
- return CoderResult.OVERFLOW;
- /* </HACK> */
- return CoderResult.UNDERFLOW;
- }
-
- /**
- * <p>
- * Writes the bytes necessary to leave <i>base 64 mode</i>. This might
- * include an unshift character.
- * </p>
- *
- * @param out
- * @param ch
- */
- private void unshift(ByteBuffer out, char ch) {
- if (!base64mode)
- return;
- if (bitsToOutput != 0)
- out.put(base64.getChar(sextet));
- if (base64.contains(ch) || ch == unshift || strict)
- out.put(unshift);
- base64mode = false;
- sextet = 0;
- bitsToOutput = 0;
- }
-
- /**
- * <p>
- * Writes the bytes necessary to encode a character in <i>base 64 mode</i>.
- * All bytes which are fully determined will be written. The fields
- * <code>bitsToOutput</code> and <code>sextet</code> are used to remember
- * the bytes not yet fully determined.
- * </p>
- *
- * @param out
- * @param ch
- */
- private void encodeBase64(char ch, ByteBuffer out) {
- if (!base64mode)
- out.put(shift);
- base64mode = true;
- bitsToOutput += 16;
- while (bitsToOutput >= 6) {
- bitsToOutput -= 6;
- sextet += (ch >> bitsToOutput);
- sextet &= 0x3F;
- out.put(base64.getChar(sextet));
- sextet = 0;
- }
- sextet = (ch << (6 - bitsToOutput)) & 0x3F;
- }
-}
diff --git a/src/org/apache/commons/io/CopyUtils.java b/src/org/apache/commons/io/CopyUtils.java
deleted file mode 100644
index eab8307e7..000000000
--- a/src/org/apache/commons/io/CopyUtils.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.Writer;
-
-/**
- * This class provides static utility methods for buffered
- * copying between sources (<code>InputStream</code>, <code>Reader</code>,
- * <code>String</code> and <code>byte[]</code>) and destinations
- * (<code>OutputStream</code>, <code>Writer</code>, <code>String</code> and
- * <code>byte[]</code>).
- * <p>
- * Unless otherwise noted, these <code>copy</code> methods do <em>not</em>
- * flush or close the streams. Often doing so would require making non-portable
- * assumptions about the streams' origin and further use. This means that both
- * streams' <code>close()</code> methods must be called after copying. if one
- * omits this step, then the stream resources (sockets, file descriptors) are
- * released when the associated Stream is garbage-collected. It is not a good
- * idea to rely on this mechanism. For a good overview of the distinction
- * between "memory management" and "resource management", see
- * <a href="http://www.unixreview.com/articles/1998/9804/9804ja/ja.htm">this
- * UnixReview article</a>.
- * <p>
- * For byte-to-char methods, a <code>copy</code> variant allows the encoding
- * to be selected (otherwise the platform default is used). We would like to
- * encourage you to always specify the encoding because relying on the platform
- * default can lead to unexpected results.
- * <p
- * We don't provide special variants for the <code>copy</code> methods that
- * let you specify the buffer size because in modern VMs the impact on speed
- * seems to be minimal. We're using a default buffer size of 4 KB.
- * <p>
- * The <code>copy</code> methods use an internal buffer when copying. It is
- * therefore advisable <em>not</em> to deliberately wrap the stream arguments
- * to the <code>copy</code> methods in <code>Buffered*</code> streams. For
- * example, don't do the following:
- * <pre>
- * copy( new BufferedInputStream( in ), new BufferedOutputStream( out ) );
- * </pre>
- * The rationale is as follows:
- * <p>
- * Imagine that an InputStream's read() is a very expensive operation, which
- * would usually suggest wrapping in a BufferedInputStream. The
- * BufferedInputStream works by issuing infrequent
- * {@link java.io.InputStream#read(byte[] b, int off, int len)} requests on the
- * underlying InputStream, to fill an internal buffer, from which further
- * <code>read</code> requests can inexpensively get their data (until the buffer
- * runs out).
- * <p>
- * However, the <code>copy</code> methods do the same thing, keeping an
- * internal buffer, populated by
- * {@link InputStream#read(byte[] b, int off, int len)} requests. Having two
- * buffers (or three if the destination stream is also buffered) is pointless,
- * and the unnecessary buffer management hurts performance slightly (about 3%,
- * according to some simple experiments).
- * <p>
- * Behold, intrepid explorers; a map of this class:
- * <pre>
- * Method Input Output Dependency
- * ------ ----- ------ -------
- * 1 copy InputStream OutputStream (primitive)
- * 2 copy Reader Writer (primitive)
- *
- * 3 copy InputStream Writer 2
- *
- * 4 copy Reader OutputStream 2
- *
- * 5 copy String OutputStream 2
- * 6 copy String Writer (trivial)
- *
- * 7 copy byte[] Writer 3
- * 8 copy byte[] OutputStream (trivial)
- * </pre>
- * <p>
- * Note that only the first two methods shuffle bytes; the rest use these
- * two, or (if possible) copy using native Java copy methods. As there are
- * method variants to specify the encoding, each row may
- * correspond to up to 2 methods.
- * <p>
- * Origin of code: Excalibur.
- *
- * @author Peter Donald
- * @author Jeff Turner
- * @author Matthew Hawthorne
- * @version $Id: CopyUtils.java 437680 2006-08-28 11:57:00Z scolebourne $
- * @deprecated Use IOUtils. Will be removed in 2.0.
- * Methods renamed to IOUtils.write() or IOUtils.copy().
- * Null handling behaviour changed in IOUtils (null data does not
- * throw NullPointerException).
- */
-public class CopyUtils {
-
- /**
- * The default size of the buffer.
- */
- private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
-
- /**
- * Instances should NOT be constructed in standard programming.
- */
- public CopyUtils() { }
-
- // ----------------------------------------------------------------
- // byte[] -> OutputStream
- // ----------------------------------------------------------------
-
- /**
- * Copy bytes from a <code>byte[]</code> to an <code>OutputStream</code>.
- * @param input the byte array to read from
- * @param output the <code>OutputStream</code> to write to
- * @throws IOException In case of an I/O problem
- */
- public static void copy(byte[] input, OutputStream output)
- throws IOException {
- output.write(input);
- }
-
- // ----------------------------------------------------------------
- // byte[] -> Writer
- // ----------------------------------------------------------------
-
- /**
- * Copy and convert bytes from a <code>byte[]</code> to chars on a
- * <code>Writer</code>.
- * The platform's default encoding is used for the byte-to-char conversion.
- * @param input the byte array to read from
- * @param output the <code>Writer</code> to write to
- * @throws IOException In case of an I/O problem
- */
- public static void copy(byte[] input, Writer output)
- throws IOException {
- ByteArrayInputStream in = new ByteArrayInputStream(input);
- copy(in, output);
- }
-
-
- /**
- * Copy and convert bytes from a <code>byte[]</code> to chars on a
- * <code>Writer</code>, using the specified encoding.
- * @param input the byte array to read from
- * @param output the <code>Writer</code> to write to
- * @param encoding The name of a supported character encoding. See the
- * <a href="http://www.iana.org/assignments/character-sets">IANA
- * Charset Registry</a> for a list of valid encoding types.
- * @throws IOException In case of an I/O problem
- */
- public static void copy(
- byte[] input,
- Writer output,
- String encoding)
- throws IOException {
- ByteArrayInputStream in = new ByteArrayInputStream(input);
- copy(in, output, encoding);
- }
-
-
- // ----------------------------------------------------------------
- // Core copy methods
- // ----------------------------------------------------------------
-
- /**
- * Copy bytes from an <code>InputStream</code> to an
- * <code>OutputStream</code>.
- * @param input the <code>InputStream</code> to read from
- * @param output the <code>OutputStream</code> to write to
- * @return the number of bytes copied
- * @throws IOException In case of an I/O problem
- */
- public static int copy(
- InputStream input,
- OutputStream output)
- throws IOException {
- byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
- int count = 0;
- int n = 0;
- while (-1 != (n = input.read(buffer))) {
- output.write(buffer, 0, n);
- count += n;
- }
- return count;
- }
-
- // ----------------------------------------------------------------
- // Reader -> Writer
- // ----------------------------------------------------------------
-
- /**
- * Copy chars from a <code>Reader</code> to a <code>Writer</code>.
- * @param input the <code>Reader</code> to read from
- * @param output the <code>Writer</code> to write to
- * @return the number of characters copied
- * @throws IOException In case of an I/O problem
- */
- public static int copy(
- Reader input,
- Writer output)
- throws IOException {
- char[] buffer = new char[DEFAULT_BUFFER_SIZE];
- int count = 0;
- int n = 0;
- while (-1 != (n = input.read(buffer))) {
- output.write(buffer, 0, n);
- count += n;
- }
- return count;
- }
-
- // ----------------------------------------------------------------
- // InputStream -> Writer
- // ----------------------------------------------------------------
-
- /**
- * Copy and convert bytes from an <code>InputStream</code> to chars on a
- * <code>Writer</code>.
- * The platform's default encoding is used for the byte-to-char conversion.
- * @param input the <code>InputStream</code> to read from
- * @param output the <code>Writer</code> to write to
- * @throws IOException In case of an I/O problem
- */
- public static void copy(
- InputStream input,
- Writer output)
- throws IOException {
- InputStreamReader in = new InputStreamReader(input);
- copy(in, output);
- }
-
- /**
- * Copy and convert bytes from an <code>InputStream</code> to chars on a
- * <code>Writer</code>, using the specified encoding.
- * @param input the <code>InputStream</code> to read from
- * @param output the <code>Writer</code> to write to
- * @param encoding The name of a supported character encoding. See the
- * <a href="http://www.iana.org/assignments/character-sets">IANA
- * Charset Registry</a> for a list of valid encoding types.
- * @throws IOException In case of an I/O problem
- */
- public static void copy(
- InputStream input,
- Writer output,
- String encoding)
- throws IOException {
- InputStreamReader in = new InputStreamReader(input, encoding);
- copy(in, output);
- }
-
-
- // ----------------------------------------------------------------
- // Reader -> OutputStream
- // ----------------------------------------------------------------
-
- /**
- * Serialize chars from a <code>Reader</code> to bytes on an
- * <code>OutputStream</code>, and flush the <code>OutputStream</code>.
- * @param input the <code>Reader</code> to read from
- * @param output the <code>OutputStream</code> to write to
- * @throws IOException In case of an I/O problem
- */
- public static void copy(
- Reader input,
- OutputStream output)
- throws IOException {
- OutputStreamWriter out = new OutputStreamWriter(output);
- copy(input, out);
- // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
- // have to flush here.
- out.flush();
- }
-
- // ----------------------------------------------------------------
- // String -> OutputStream
- // ----------------------------------------------------------------
-
- /**
- * Serialize chars from a <code>String</code> to bytes on an
- * <code>OutputStream</code>, and
- * flush the <code>OutputStream</code>.
- * @param input the <code>String</code> to read from
- * @param output the <code>OutputStream</code> to write to
- * @throws IOException In case of an I/O problem
- */
- public static void copy(
- String input,
- OutputStream output)
- throws IOException {
- StringReader in = new StringReader(input);
- OutputStreamWriter out = new OutputStreamWriter(output);
- copy(in, out);
- // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
- // have to flush here.
- out.flush();
- }
-
- // ----------------------------------------------------------------
- // String -> Writer
- // ----------------------------------------------------------------
-
- /**
- * Copy chars from a <code>String</code> to a <code>Writer</code>.
- * @param input the <code>String</code> to read from
- * @param output the <code>Writer</code> to write to
- * @throws IOException In case of an I/O problem
- */
- public static void copy(String input, Writer output)
- throws IOException {
- output.write(input);
- }
-
-}
diff --git a/src/org/apache/commons/io/DirectoryWalker.java b/src/org/apache/commons/io/DirectoryWalker.java
deleted file mode 100644
index 9e564ae86..000000000
--- a/src/org/apache/commons/io/DirectoryWalker.java
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.IOException;
-import java.util.Collection;
-
-import org.apache.commons.io.filefilter.FileFilterUtils;
-import org.apache.commons.io.filefilter.IOFileFilter;
-import org.apache.commons.io.filefilter.TrueFileFilter;
-
-/**
- * Abstract class that walks through a directory hierarchy and provides
- * subclasses with convenient hooks to add specific behaviour.
- * <p>
- * This class operates with a {@link FileFilter} and maximum depth to
- * limit the files and direcories visited.
- * Commons IO supplies many common filter implementations in the
- * <a href="filefilter/package-summary.html"> filefilter</a> package.
- * <p>
- * The following sections describe:
- * <ul>
- * <li><a href="#example">1. Example Implementation</a> - example
- * <code>FileCleaner</code> implementation.</li>
- * <li><a href="#filter">2. Filter Example</a> - using
- * {@link FileFilter}(s) with <code>DirectoryWalker</code>.</li>
- * <li><a href="#cancel">3. Cancellation</a> - how to implement cancellation
- * behaviour.</li>
- * </ul>
- *
- * <a name="example"></a>
- * <h3>1. Example Implementation</h3>
- *
- * There are many possible extensions, for example, to delete all
- * files and '.svn' directories, and return a list of deleted files:
- * <pre>
- * public class FileCleaner extends DirectoryWalker {
- *
- * public FileCleaner() {
- * super();
- * }
- *
- * public List clean(File startDirectory) {
- * List results = new ArrayList();
- * walk(startDirectory, results);
- * return results;
- * }
- *
- * protected boolean handleDirectory(File directory, int depth, Collection results) {
- * // delete svn directories and then skip
- * if (".svn".equals(directory.getName())) {
- * directory.delete();
- * return false;
- * } else {
- * return true;
- * }
- *
- * }
- *
- * protected void handleFile(File file, int depth, Collection results) {
- * // delete file and add to list of deleted
- * file.delete();
- * results.add(file);
- * }
- * }
- * </pre>
- *
- * <a name="filter"></a>
- * <h3>2. Filter Example</h3>
- *
- * Choosing which directories and files to process can be a key aspect
- * of using this class. This information can be setup in three ways,
- * via three different constructors.
- * <p>
- * The first option is to visit all directories and files.
- * This is achieved via the no-args constructor.
- * <p>
- * The second constructor option is to supply a single {@link FileFilter}
- * that describes the files and directories to visit. Care must be taken
- * with this option as the same filter is used for both directories
- * and files.
- * <p>
- * For example, if you wanted all directories which are not hidden
- * and files which end in ".txt":
- * <pre>
- * public class FooDirectoryWalker extends DirectoryWalker {
- * public FooDirectoryWalker(FileFilter filter) {
- * super(filter, -1);
- * }
- * }
- *
- * // Build up the filters and create the walker
- * // Create a filter for Non-hidden directories
- * IOFileFilter fooDirFilter =
- * FileFilterUtils.andFileFilter(FileFilterUtils.directoryFileFilter,
- * HiddenFileFilter.VISIBLE);
- *
- * // Create a filter for Files ending in ".txt"
- * IOFileFilter fooFileFilter =
- * FileFilterUtils.andFileFilter(FileFilterUtils.fileFileFilter,
- * FileFilterUtils.suffixFileFilter(".txt"));
- *
- * // Combine the directory and file filters using an OR condition
- * java.io.FileFilter fooFilter =
- * FileFilterUtils.orFileFilter(fooDirFilter, fooFileFilter);
- *
- * // Use the filter to construct a DirectoryWalker implementation
- * FooDirectoryWalker walker = new FooDirectoryWalker(fooFilter);
- * </pre>
- * <p>
- * The third constructor option is to specify separate filters, one for
- * directories and one for files. These are combined internally to form
- * the correct <code>FileFilter</code>, something which is very easy to
- * get wrong when attempted manually, particularly when trying to
- * express constructs like 'any file in directories named docs'.
- * <p>
- * For example, if you wanted all directories which are not hidden
- * and files which end in ".txt":
- * <pre>
- * public class FooDirectoryWalker extends DirectoryWalker {
- * public FooDirectoryWalker(IOFileFilter dirFilter, IOFileFilter fileFilter) {
- * super(dirFilter, fileFilter, -1);
- * }
- * }
- *
- * // Use the filters to construct the walker
- * FooDirectoryWalker walker = new FooDirectoryWalker(
- * HiddenFileFilter.VISIBLE,
- * FileFilterUtils.suffixFileFilter(".txt"),
- * );
- * </pre>
- * This is much simpler than the previous example, and is why it is the preferred
- * option for filtering.
- *
- * <a name="cancel"></a>
- * <h3>3. Cancellation</h3>
- *
- * The DirectoryWalker contains some of the logic required for cancel processing.
- * Subclasses must complete the implementation.
- * <p>
- * What <code>DirectoryWalker</code> does provide for cancellation is:
- * <ul>
- * <li>{@link CancelException} which can be thrown in any of the
- * <i>lifecycle</i> methods to stop processing.</li>
- * <li>The <code>walk()</code> method traps thrown {@link CancelException}
- * and calls the <code>handleCancelled()</code> method, providing
- * a place for custom cancel processing.</li>
- * </ul>
- * <p>
- * Implementations need to provide:
- * <ul>
- * <li>The decision logic on whether to cancel processing or not.</li>
- * <li>Constructing and throwing a {@link CancelException}.</li>
- * <li>Custom cancel processing in the <code>handleCancelled()</code> method.
- * </ul>
- * <p>
- * Two possible scenarios are envisaged for cancellation:
- * <ul>
- * <li><a href="#external">3.1 External / Mult-threaded</a> - cancellation being
- * decided/initiated by an external process.</li>
- * <li><a href="#internal">3.2 Internal</a> - cancellation being decided/initiated
- * from within a DirectoryWalker implementation.</li>
- * </ul>
- * <p>
- * The following sections provide example implementations for these two different
- * scenarios.
- *
- * <a name="external"></a>
- * <h4>3.1 External / Multi-threaded</h4>
- *
- * This example provides a public <code>cancel()</code> method that can be
- * called by another thread to stop the processing. A typical example use-case
- * would be a cancel button on a GUI. Calling this method sets a
- * <a href="http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#36930">
- * volatile</a> flag to ensure it will work properly in a multi-threaded environment.
- * The flag is returned by the <code>handleIsCancelled()</code> method, which
- * will cause the walk to stop immediately. The <code>handleCancelled()</code>
- * method will be the next, and last, callback method received once cancellation
- * has occurred.
- *
- * <pre>
- * public class FooDirectoryWalker extends DirectoryWalker {
- *
- * private volatile boolean cancelled = false;
- *
- * public void cancel() {
- * cancelled = true;
- * }
- *
- * private void handleIsCancelled(File file, int depth, Collection results) {
- * return cancelled;
- * }
- *
- * protected void handleCancelled(File startDirectory, Collection results, CancelException cancel) {
- * // implement processing required when a cancellation occurs
- * }
- * }
- * </pre>
- *
- * <a name="internal"></a>
- * <h4>3.2 Internal</h4>
- *
- * This shows an example of how internal cancellation processing could be implemented.
- * <b>Note</b> the decision logic and throwing a {@link CancelException} could be implemented
- * in any of the <i>lifecycle</i> methods.
- *
- * <pre>
- * public class BarDirectoryWalker extends DirectoryWalker {
- *
- * protected boolean handleDirectory(File directory, int depth, Collection results) throws IOException {
- * // cancel if hidden directory
- * if (directory.isHidden()) {
- * throw new CancelException(file, depth);
- * }
- * return true;
- * }
- *
- * protected void handleFile(File file, int depth, Collection results) throws IOException {
- * // cancel if read-only file
- * if (!file.canWrite()) {
- * throw new CancelException(file, depth);
- * }
- * results.add(file);
- * }
- *
- * protected void handleCancelled(File startDirectory, Collection results, CancelException cancel) {
- * // implement processing required when a cancellation occurs
- * }
- * }
- * </pre>
- *
- * @since Commons IO 1.3
- * @version $Revision: 424748 $
- */
-public abstract class DirectoryWalker {
-
- /**
- * The file filter to use to filter files and directories.
- */
- private final FileFilter filter;
- /**
- * The limit on the directory depth to walk.
- */
- private final int depthLimit;
-
- /**
- * Construct an instance with no filtering and unlimited <i>depth</i>.
- */
- protected DirectoryWalker() {
- this(null, -1);
- }
-
- /**
- * Construct an instance with a filter and limit the <i>depth</i> navigated to.
- * <p>
- * The filter controls which files and directories will be navigated to as
- * part of the walk. The {@link FileFilterUtils} class is useful for combining
- * various filters together. A <code>null</code> filter means that no
- * filtering should occur and all files and directories will be visited.
- *
- * @param filter the filter to apply, null means visit all files
- * @param depthLimit controls how <i>deep</i> the hierarchy is
- * navigated to (less than 0 means unlimited)
- */
- protected DirectoryWalker(FileFilter filter, int depthLimit) {
- this.filter = filter;
- this.depthLimit = depthLimit;
- }
-
- /**
- * Construct an instance with a directory and a file filter and an optional
- * limit on the <i>depth</i> navigated to.
- * <p>
- * The filters control which files and directories will be navigated to as part
- * of the walk. This constructor uses {@link FileFilterUtils#makeDirectoryOnly(IOFileFilter)}
- * and {@link FileFilterUtils#makeFileOnly(IOFileFilter)} internally to combine the filters.
- * A <code>null</code> filter means that no filtering should occur.
- *
- * @param directoryFilter the filter to apply to directories, null means visit all directories
- * @param fileFilter the filter to apply to files, null means visit all files
- * @param depthLimit controls how <i>deep</i> the hierarchy is
- * navigated to (less than 0 means unlimited)
- */
- protected DirectoryWalker(IOFileFilter directoryFilter, IOFileFilter fileFilter, int depthLimit) {
- if (directoryFilter == null && fileFilter == null) {
- this.filter = null;
- } else {
- directoryFilter = (directoryFilter != null ? directoryFilter : TrueFileFilter.TRUE);
- fileFilter = (fileFilter != null ? fileFilter : TrueFileFilter.TRUE);
- directoryFilter = FileFilterUtils.makeDirectoryOnly(directoryFilter);
- fileFilter = FileFilterUtils.makeFileOnly(fileFilter);
- this.filter = FileFilterUtils.orFileFilter(directoryFilter, fileFilter);
- }
- this.depthLimit = depthLimit;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Internal method that walks the directory hierarchy in a depth-first manner.
- * <p>
- * Users of this class do not need to call this method. This method will
- * be called automatically by another (public) method on the specific subclass.
- * <p>
- * Writers of subclasses should call this method to start the directory walk.
- * Once called, this method will emit events as it walks the hierarchy.
- * The event methods have the prefix <code>handle</code>.
- *
- * @param startDirectory the directory to start from, not null
- * @param results the collection of result objects, may be updated
- * @throws NullPointerException if the start directory is null
- * @throws IOException if an I/O Error occurs
- */
- protected final void walk(File startDirectory, Collection results) throws IOException {
- if (startDirectory == null) {
- throw new NullPointerException("Start Directory is null");
- }
- try {
- handleStart(startDirectory, results);
- walk(startDirectory, 0, results);
- handleEnd(results);
- } catch(CancelException cancel) {
- handleCancelled(startDirectory, results, cancel);
- }
- }
-
- /**
- * Main recursive method to examine the directory hierarchy.
- *
- * @param directory the directory to examine, not null
- * @param depth the directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
- */
- private void walk(File directory, int depth, Collection results) throws IOException {
- checkIfCancelled(directory, depth, results);
- if (handleDirectory(directory, depth, results)) {
- handleDirectoryStart(directory, depth, results);
- int childDepth = depth + 1;
- if (depthLimit < 0 || childDepth <= depthLimit) {
- checkIfCancelled(directory, depth, results);
- File[] childFiles = (filter == null ? directory.listFiles() : directory.listFiles(filter));
- if (childFiles == null) {
- handleRestricted(directory, childDepth, results);
- } else {
- for (int i = 0; i < childFiles.length; i++) {
- File childFile = childFiles[i];
- if (childFile.isDirectory()) {
- walk(childFile, childDepth, results);
- } else {
- checkIfCancelled(childFile, childDepth, results);
- handleFile(childFile, childDepth, results);
- checkIfCancelled(childFile, childDepth, results);
- }
- }
- }
- }
- handleDirectoryEnd(directory, depth, results);
- }
- checkIfCancelled(directory, depth, results);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Checks whether the walk has been cancelled by calling {@link #handleIsCancelled},
- * throwing a <code>CancelException</code> if it has.
- * <p>
- * Writers of subclasses should not normally call this method as it is called
- * automatically by the walk of the tree. However, sometimes a single method,
- * typically {@link #handleFile}, may take a long time to run. In that case,
- * you may wish to check for cancellation by calling this method.
- *
- * @param file the current file being processed
- * @param depth the current file level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
- */
- protected final void checkIfCancelled(File file, int depth, Collection results) throws IOException {
- if (handleIsCancelled(file, depth, results)) {
- throw new CancelException(file, depth);
- }
- }
-
- /**
- * Overridable callback method invoked to determine if the entire walk
- * operation should be immediately cancelled.
- * <p>
- * This method should be implemented by those subclasses that want to
- * provide a public <code>cancel()</code> method available from another
- * thread. The design pattern for the subclass should be as follows:
- * <pre>
- * public class FooDirectoryWalker extends DirectoryWalker {
- * private volatile boolean cancelled = false;
- *
- * public void cancel() {
- * cancelled = true;
- * }
- * private void handleIsCancelled(File file, int depth, Collection results) {
- * return cancelled;
- * }
- * protected void handleCancelled(File startDirectory,
- * Collection results, CancelException cancel) {
- * // implement processing required when a cancellation occurs
- * }
- * }
- * </pre>
- * <p>
- * If this method returns true, then the directory walk is immediately
- * cancelled. The next callback method will be {@link #handleCancelled}.
- * <p>
- * This implementation returns false.
- *
- * @param file the file or directory being processed
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @return true if the walk has been cancelled
- * @throws IOException if an I/O Error occurs
- */
- protected boolean handleIsCancelled(
- File file, int depth, Collection results) throws IOException {
- // do nothing - overridable by subclass
- return false; // not cancelled
- }
-
- /**
- * Overridable callback method invoked when the operation is cancelled.
- * The file being processed when the cancellation occurred can be
- * obtained from the exception.
- * <p>
- * This implementation just re-throws the {@link CancelException}.
- *
- * @param startDirectory the directory that the walk started from
- * @param results the collection of result objects, may be updated
- * @param cancel the exception throw to cancel further processing
- * containing details at the point of cancellation.
- * @throws IOException if an I/O Error occurs
- */
- protected void handleCancelled(File startDirectory, Collection results,
- CancelException cancel) throws IOException {
- // re-throw exception - overridable by subclass
- throw cancel;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Overridable callback method invoked at the start of processing.
- * <p>
- * This implementation does nothing.
- *
- * @param startDirectory the directory to start from
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
- */
- protected void handleStart(File startDirectory, Collection results) throws IOException {
- // do nothing - overridable by subclass
- }
-
- /**
- * Overridable callback method invoked to determine if a directory should be processed.
- * <p>
- * This method returns a boolean to indicate if the directory should be examined or not.
- * If you return false, the entire directory and any subdirectories will be skipped.
- * Note that this functionality is in addition to the filtering by file filter.
- * <p>
- * This implementation does nothing and returns true.
- *
- * @param directory the current directory being processed
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @return true to process this directory, false to skip this directory
- * @throws IOException if an I/O Error occurs
- */
- protected boolean handleDirectory(File directory, int depth, Collection results) throws IOException {
- // do nothing - overridable by subclass
- return true; // process directory
- }
-
- /**
- * Overridable callback method invoked at the start of processing each directory.
- * <p>
- * This implementation does nothing.
- *
- * @param directory the current directory being processed
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
- */
- protected void handleDirectoryStart(File directory, int depth, Collection results) throws IOException {
- // do nothing - overridable by subclass
- }
-
- /**
- * Overridable callback method invoked for each (non-directory) file.
- * <p>
- * This implementation does nothing.
- *
- * @param file the current file being processed
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
- */
- protected void handleFile(File file, int depth, Collection results) throws IOException {
- // do nothing - overridable by subclass
- }
-
- /**
- * Overridable callback method invoked for each restricted directory.
- * <p>
- * This implementation does nothing.
- *
- * @param directory the restricted directory
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
- */
- protected void handleRestricted(File directory, int depth, Collection results) throws IOException {
- // do nothing - overridable by subclass
- }
-
- /**
- * Overridable callback method invoked at the end of processing each directory.
- * <p>
- * This implementation does nothing.
- *
- * @param directory the directory being processed
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
- */
- protected void handleDirectoryEnd(File directory, int depth, Collection results) throws IOException {
- // do nothing - overridable by subclass
- }
-
- /**
- * Overridable callback method invoked at the end of processing.
- * <p>
- * This implementation does nothing.
- *
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
- */
- protected void handleEnd(Collection results) throws IOException {
- // do nothing - overridable by subclass
- }
-
- //-----------------------------------------------------------------------
- /**
- * CancelException is thrown in DirectoryWalker to cancel the current
- * processing.
- */
- public static class CancelException extends IOException {
-
- /** Serialization id. */
- private static final long serialVersionUID = 1347339620135041008L;
-
- /** The file being processed when the exception was thrown. */
- private File file;
- /** The file depth when the exception was thrown. */
- private int depth = -1;
-
- /**
- * Constructs a <code>CancelException</code> with
- * the file and depth when cancellation occurred.
- *
- * @param file the file when the operation was cancelled, may be null
- * @param depth the depth when the operation was cancelled, may be null
- */
- public CancelException(File file, int depth) {
- this("Operation Cancelled", file, depth);
- }
-
- /**
- * Constructs a <code>CancelException</code> with
- * an appropriate message and the file and depth when
- * cancellation occurred.
- *
- * @param message the detail message
- * @param file the file when the operation was cancelled
- * @param depth the depth when the operation was cancelled
- */
- public CancelException(String message, File file, int depth) {
- super(message);
- this.file = file;
- this.depth = depth;
- }
-
- /**
- * Return the file when the operation was cancelled.
- *
- * @return the file when the operation was cancelled
- */
- public File getFile() {
- return file;
- }
-
- /**
- * Return the depth when the operation was cancelled.
- *
- * @return the depth when the operation was cancelled
- */
- public int getDepth() {
- return depth;
- }
- }
-}
diff --git a/src/org/apache/commons/io/EndianUtils.java b/src/org/apache/commons/io/EndianUtils.java
deleted file mode 100644
index 810feac04..000000000
--- a/src/org/apache/commons/io/EndianUtils.java
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Utility code for dealing with different endian systems.
- * <p>
- * Different computer architectures adopt different conventions for
- * byte ordering. In so-called "Little Endian" architectures (eg Intel),
- * the low-order byte is stored in memory at the lowest address, and
- * subsequent bytes at higher addresses. For "Big Endian" architectures
- * (eg Motorola), the situation is reversed.
- * This class helps you solve this incompatability.
- * <p>
- * Origin of code: Excalibur
- *
- * @author <a href="mailto:peter@apache.org">Peter Donald</a>
- * @version $Id: EndianUtils.java 539632 2007-05-18 23:37:59Z bayard $
- * @see org.apache.commons.io.input.SwappedDataInputStream
- */
-public class EndianUtils {
-
- /**
- * Instances should NOT be constructed in standard programming.
- */
- public EndianUtils() {
- super();
- }
-
- // ========================================== Swapping routines
-
- /**
- * Converts a "short" value between endian systems.
- * @param value value to convert
- * @return the converted value
- */
- public static short swapShort(short value) {
- return (short) ( ( ( ( value >> 0 ) & 0xff ) << 8 ) +
- ( ( ( value >> 8 ) & 0xff ) << 0 ) );
- }
-
- /**
- * Converts a "int" value between endian systems.
- * @param value value to convert
- * @return the converted value
- */
- public static int swapInteger(int value) {
- return
- ( ( ( value >> 0 ) & 0xff ) << 24 ) +
- ( ( ( value >> 8 ) & 0xff ) << 16 ) +
- ( ( ( value >> 16 ) & 0xff ) << 8 ) +
- ( ( ( value >> 24 ) & 0xff ) << 0 );
- }
-
- /**
- * Converts a "long" value between endian systems.
- * @param value value to convert
- * @return the converted value
- */
- public static long swapLong(long value) {
- return
- ( ( ( value >> 0 ) & 0xff ) << 56 ) +
- ( ( ( value >> 8 ) & 0xff ) << 48 ) +
- ( ( ( value >> 16 ) & 0xff ) << 40 ) +
- ( ( ( value >> 24 ) & 0xff ) << 32 ) +
- ( ( ( value >> 32 ) & 0xff ) << 24 ) +
- ( ( ( value >> 40 ) & 0xff ) << 16 ) +
- ( ( ( value >> 48 ) & 0xff ) << 8 ) +
- ( ( ( value >> 56 ) & 0xff ) << 0 );
- }
-
- /**
- * Converts a "float" value between endian systems.
- * @param value value to convert
- * @return the converted value
- */
- public static float swapFloat(float value) {
- return Float.intBitsToFloat( swapInteger( Float.floatToIntBits( value ) ) );
- }
-
- /**
- * Converts a "double" value between endian systems.
- * @param value value to convert
- * @return the converted value
- */
- public static double swapDouble(double value) {
- return Double.longBitsToDouble( swapLong( Double.doubleToLongBits( value ) ) );
- }
-
- // ========================================== Swapping read/write routines
-
- /**
- * Writes a "short" value to a byte array at a given offset. The value is
- * converted to the opposed endian system while writing.
- * @param data target byte array
- * @param offset starting offset in the byte array
- * @param value value to write
- */
- public static void writeSwappedShort(byte[] data, int offset, short value) {
- data[ offset + 0 ] = (byte)( ( value >> 0 ) & 0xff );
- data[ offset + 1 ] = (byte)( ( value >> 8 ) & 0xff );
- }
-
- /**
- * Reads a "short" value from a byte array at a given offset. The value is
- * converted to the opposed endian system while reading.
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- */
- public static short readSwappedShort(byte[] data, int offset) {
- return (short)( ( ( data[ offset + 0 ] & 0xff ) << 0 ) +
- ( ( data[ offset + 1 ] & 0xff ) << 8 ) );
- }
-
- /**
- * Reads an unsigned short (16-bit) value from a byte array at a given
- * offset. The value is converted to the opposed endian system while
- * reading.
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- */
- public static int readSwappedUnsignedShort(byte[] data, int offset) {
- return ( ( ( data[ offset + 0 ] & 0xff ) << 0 ) +
- ( ( data[ offset + 1 ] & 0xff ) << 8 ) );
- }
-
- /**
- * Writes a "int" value to a byte array at a given offset. The value is
- * converted to the opposed endian system while writing.
- * @param data target byte array
- * @param offset starting offset in the byte array
- * @param value value to write
- */
- public static void writeSwappedInteger(byte[] data, int offset, int value) {
- data[ offset + 0 ] = (byte)( ( value >> 0 ) & 0xff );
- data[ offset + 1 ] = (byte)( ( value >> 8 ) & 0xff );
- data[ offset + 2 ] = (byte)( ( value >> 16 ) & 0xff );
- data[ offset + 3 ] = (byte)( ( value >> 24 ) & 0xff );
- }
-
- /**
- * Reads a "int" value from a byte array at a given offset. The value is
- * converted to the opposed endian system while reading.
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- */
- public static int readSwappedInteger(byte[] data, int offset) {
- return ( ( ( data[ offset + 0 ] & 0xff ) << 0 ) +
- ( ( data[ offset + 1 ] & 0xff ) << 8 ) +
- ( ( data[ offset + 2 ] & 0xff ) << 16 ) +
- ( ( data[ offset + 3 ] & 0xff ) << 24 ) );
- }
-
- /**
- * Reads an unsigned integer (32-bit) value from a byte array at a given
- * offset. The value is converted to the opposed endian system while
- * reading.
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- */
- public static long readSwappedUnsignedInteger(byte[] data, int offset) {
- long low = ( ( ( data[ offset + 0 ] & 0xff ) << 0 ) +
- ( ( data[ offset + 1 ] & 0xff ) << 8 ) +
- ( ( data[ offset + 2 ] & 0xff ) << 16 ) );
-
- long high = data[ offset + 3 ] & 0xff;
-
- return (high << 24) + (0xffffffffL & low);
- }
-
- /**
- * Writes a "long" value to a byte array at a given offset. The value is
- * converted to the opposed endian system while writing.
- * @param data target byte array
- * @param offset starting offset in the byte array
- * @param value value to write
- */
- public static void writeSwappedLong(byte[] data, int offset, long value) {
- data[ offset + 0 ] = (byte)( ( value >> 0 ) & 0xff );
- data[ offset + 1 ] = (byte)( ( value >> 8 ) & 0xff );
- data[ offset + 2 ] = (byte)( ( value >> 16 ) & 0xff );
- data[ offset + 3 ] = (byte)( ( value >> 24 ) & 0xff );
- data[ offset + 4 ] = (byte)( ( value >> 32 ) & 0xff );
- data[ offset + 5 ] = (byte)( ( value >> 40 ) & 0xff );
- data[ offset + 6 ] = (byte)( ( value >> 48 ) & 0xff );
- data[ offset + 7 ] = (byte)( ( value >> 56 ) & 0xff );
- }
-
- /**
- * Reads a "long" value from a byte array at a given offset. The value is
- * converted to the opposed endian system while reading.
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- */
- public static long readSwappedLong(byte[] data, int offset) {
- long low =
- ( ( data[ offset + 0 ] & 0xff ) << 0 ) +
- ( ( data[ offset + 1 ] & 0xff ) << 8 ) +
- ( ( data[ offset + 2 ] & 0xff ) << 16 ) +
- ( ( data[ offset + 3 ] & 0xff ) << 24 );
- long high =
- ( ( data[ offset + 4 ] & 0xff ) << 0 ) +
- ( ( data[ offset + 5 ] & 0xff ) << 8 ) +
- ( ( data[ offset + 6 ] & 0xff ) << 16 ) +
- ( ( data[ offset + 7 ] & 0xff ) << 24 );
- return (high << 32) + (0xffffffffL & low);
- }
-
- /**
- * Writes a "float" value to a byte array at a given offset. The value is
- * converted to the opposed endian system while writing.
- * @param data target byte array
- * @param offset starting offset in the byte array
- * @param value value to write
- */
- public static void writeSwappedFloat(byte[] data, int offset, float value) {
- writeSwappedInteger( data, offset, Float.floatToIntBits( value ) );
- }
-
- /**
- * Reads a "float" value from a byte array at a given offset. The value is
- * converted to the opposed endian system while reading.
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- */
- public static float readSwappedFloat(byte[] data, int offset) {
- return Float.intBitsToFloat( readSwappedInteger( data, offset ) );
- }
-
- /**
- * Writes a "double" value to a byte array at a given offset. The value is
- * converted to the opposed endian system while writing.
- * @param data target byte array
- * @param offset starting offset in the byte array
- * @param value value to write
- */
- public static void writeSwappedDouble(byte[] data, int offset, double value) {
- writeSwappedLong( data, offset, Double.doubleToLongBits( value ) );
- }
-
- /**
- * Reads a "double" value from a byte array at a given offset. The value is
- * converted to the opposed endian system while reading.
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- */
- public static double readSwappedDouble(byte[] data, int offset) {
- return Double.longBitsToDouble( readSwappedLong( data, offset ) );
- }
-
- /**
- * Writes a "short" value to an OutputStream. The value is
- * converted to the opposed endian system while writing.
- * @param output target OutputStream
- * @param value value to write
- * @throws IOException in case of an I/O problem
- */
- public static void writeSwappedShort(OutputStream output, short value)
- throws IOException
- {
- output.write( (byte)( ( value >> 0 ) & 0xff ) );
- output.write( (byte)( ( value >> 8 ) & 0xff ) );
- }
-
- /**
- * Reads a "short" value from an InputStream. The value is
- * converted to the opposed endian system while reading.
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
- */
- public static short readSwappedShort(InputStream input)
- throws IOException
- {
- return (short)( ( ( read( input ) & 0xff ) << 0 ) +
- ( ( read( input ) & 0xff ) << 8 ) );
- }
-
- /**
- * Reads a unsigned short (16-bit) from an InputStream. The value is
- * converted to the opposed endian system while reading.
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
- */
- public static int readSwappedUnsignedShort(InputStream input)
- throws IOException
- {
- int value1 = read( input );
- int value2 = read( input );
-
- return ( ( ( value1 & 0xff ) << 0 ) +
- ( ( value2 & 0xff ) << 8 ) );
- }
-
- /**
- * Writes a "int" value to an OutputStream. The value is
- * converted to the opposed endian system while writing.
- * @param output target OutputStream
- * @param value value to write
- * @throws IOException in case of an I/O problem
- */
- public static void writeSwappedInteger(OutputStream output, int value)
- throws IOException
- {
- output.write( (byte)( ( value >> 0 ) & 0xff ) );
- output.write( (byte)( ( value >> 8 ) & 0xff ) );
- output.write( (byte)( ( value >> 16 ) & 0xff ) );
- output.write( (byte)( ( value >> 24 ) & 0xff ) );
- }
-
- /**
- * Reads a "int" value from an InputStream. The value is
- * converted to the opposed endian system while reading.
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
- */
- public static int readSwappedInteger(InputStream input)
- throws IOException
- {
- int value1 = read( input );
- int value2 = read( input );
- int value3 = read( input );
- int value4 = read( input );
-
- return ( ( value1 & 0xff ) << 0 ) +
- ( ( value2 & 0xff ) << 8 ) +
- ( ( value3 & 0xff ) << 16 ) +
- ( ( value4 & 0xff ) << 24 );
- }
-
- /**
- * Reads a unsigned integer (32-bit) from an InputStream. The value is
- * converted to the opposed endian system while reading.
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
- */
- public static long readSwappedUnsignedInteger(InputStream input)
- throws IOException
- {
- int value1 = read( input );
- int value2 = read( input );
- int value3 = read( input );
- int value4 = read( input );
-
- long low = ( ( ( value1 & 0xff ) << 0 ) +
- ( ( value2 & 0xff ) << 8 ) +
- ( ( value3 & 0xff ) << 16 ) );
-
- long high = value4 & 0xff;
-
- return (high << 24) + (0xffffffffL & low);
- }
-
- /**
- * Writes a "long" value to an OutputStream. The value is
- * converted to the opposed endian system while writing.
- * @param output target OutputStream
- * @param value value to write
- * @throws IOException in case of an I/O problem
- */
- public static void writeSwappedLong(OutputStream output, long value)
- throws IOException
- {
- output.write( (byte)( ( value >> 0 ) & 0xff ) );
- output.write( (byte)( ( value >> 8 ) & 0xff ) );
- output.write( (byte)( ( value >> 16 ) & 0xff ) );
- output.write( (byte)( ( value >> 24 ) & 0xff ) );
- output.write( (byte)( ( value >> 32 ) & 0xff ) );
- output.write( (byte)( ( value >> 40 ) & 0xff ) );
- output.write( (byte)( ( value >> 48 ) & 0xff ) );
- output.write( (byte)( ( value >> 56 ) & 0xff ) );
- }
-
- /**
- * Reads a "long" value from an InputStream. The value is
- * converted to the opposed endian system while reading.
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
- */
- public static long readSwappedLong(InputStream input)
- throws IOException
- {
- byte[] bytes = new byte[8];
- for ( int i=0; i<8; i++ ) {
- bytes[i] = (byte) read( input );
- }
- return readSwappedLong( bytes, 0 );
- }
-
- /**
- * Writes a "float" value to an OutputStream. The value is
- * converted to the opposed endian system while writing.
- * @param output target OutputStream
- * @param value value to write
- * @throws IOException in case of an I/O problem
- */
- public static void writeSwappedFloat(OutputStream output, float value)
- throws IOException
- {
- writeSwappedInteger( output, Float.floatToIntBits( value ) );
- }
-
- /**
- * Reads a "float" value from an InputStream. The value is
- * converted to the opposed endian system while reading.
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
- */
- public static float readSwappedFloat(InputStream input)
- throws IOException
- {
- return Float.intBitsToFloat( readSwappedInteger( input ) );
- }
-
- /**
- * Writes a "double" value to an OutputStream. The value is
- * converted to the opposed endian system while writing.
- * @param output target OutputStream
- * @param value value to write
- * @throws IOException in case of an I/O problem
- */
- public static void writeSwappedDouble(OutputStream output, double value)
- throws IOException
- {
- writeSwappedLong( output, Double.doubleToLongBits( value ) );
- }
-
- /**
- * Reads a "double" value from an InputStream. The value is
- * converted to the opposed endian system while reading.
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
- */
- public static double readSwappedDouble(InputStream input)
- throws IOException
- {
- return Double.longBitsToDouble( readSwappedLong( input ) );
- }
-
- /**
- * Reads the next byte from the input stream.
- * @param input the stream
- * @return the byte
- * @throws IOException if the end of file is reached
- */
- private static int read(InputStream input)
- throws IOException
- {
- int value = input.read();
-
- if( -1 == value ) {
- throw new EOFException( "Unexpected EOF reached" );
- }
-
- return value;
- }
-}
diff --git a/src/org/apache/commons/io/FileCleaner.java b/src/org/apache/commons/io/FileCleaner.java
deleted file mode 100644
index 59c2f4109..000000000
--- a/src/org/apache/commons/io/FileCleaner.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io;
-
-import java.io.File;
-
-/**
- * Keeps track of files awaiting deletion, and deletes them when an associated
- * marker object is reclaimed by the garbage collector.
- * <p>
- * This utility creates a background thread to handle file deletion.
- * Each file to be deleted is registered with a handler object.
- * When the handler object is garbage collected, the file is deleted.
- * <p>
- * In an environment with multiple class loaders (a servlet container, for
- * example), you should consider stopping the background thread if it is no
- * longer needed. This is done by invoking the method
- * {@link #exitWhenFinished}, typically in
- * {@link javax.servlet.ServletContextListener#contextDestroyed} or similar.
- *
- * @author Noel Bergman
- * @author Martin Cooper
- * @version $Id: FileCleaner.java 553012 2007-07-03 23:01:07Z ggregory $
- * @deprecated Use {@link FileCleaningTracker}
- */
-public class FileCleaner {
- /**
- * The instance to use for the deprecated, static methods.
- */
- static final FileCleaningTracker theInstance = new FileCleaningTracker();
-
- //-----------------------------------------------------------------------
- /**
- * Track the specified file, using the provided marker, deleting the file
- * when the marker instance is garbage collected.
- * The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used.
- *
- * @param file the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @throws NullPointerException if the file is null
- * @deprecated Use {@link FileCleaningTracker#track(File, Object)}.
- */
- public static void track(File file, Object marker) {
- theInstance.track(file, marker);
- }
-
- /**
- * Track the specified file, using the provided marker, deleting the file
- * when the marker instance is garbage collected.
- * The speified deletion strategy is used.
- *
- * @param file the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @param deleteStrategy the strategy to delete the file, null means normal
- * @throws NullPointerException if the file is null
- * @deprecated Use {@link FileCleaningTracker#track(File, Object, FileDeleteStrategy)}.
- */
- public static void track(File file, Object marker, FileDeleteStrategy deleteStrategy) {
- theInstance.track(file, marker, deleteStrategy);
- }
-
- /**
- * Track the specified file, using the provided marker, deleting the file
- * when the marker instance is garbage collected.
- * The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used.
- *
- * @param path the full path to the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @throws NullPointerException if the path is null
- * @deprecated Use {@link FileCleaningTracker#track(String, Object)}.
- */
- public static void track(String path, Object marker) {
- theInstance.track(path, marker);
- }
-
- /**
- * Track the specified file, using the provided marker, deleting the file
- * when the marker instance is garbage collected.
- * The speified deletion strategy is used.
- *
- * @param path the full path to the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @param deleteStrategy the strategy to delete the file, null means normal
- * @throws NullPointerException if the path is null
- * @deprecated Use {@link FileCleaningTracker#track(String, Object, FileDeleteStrategy)}.
- */
- public static void track(String path, Object marker, FileDeleteStrategy deleteStrategy) {
- theInstance.track(path, marker, deleteStrategy);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Retrieve the number of files currently being tracked, and therefore
- * awaiting deletion.
- *
- * @return the number of files being tracked
- * @deprecated Use {@link FileCleaningTracker#getTrackCount()}.
- */
- public static int getTrackCount() {
- return theInstance.getTrackCount();
- }
-
- /**
- * Call this method to cause the file cleaner thread to terminate when
- * there are no more objects being tracked for deletion.
- * <p>
- * In a simple environment, you don't need this method as the file cleaner
- * thread will simply exit when the JVM exits. In a more complex environment,
- * with multiple class loaders (such as an application server), you should be
- * aware that the file cleaner thread will continue running even if the class
- * loader it was started from terminates. This can consitute a memory leak.
- * <p>
- * For example, suppose that you have developed a web application, which
- * contains the commons-io jar file in your WEB-INF/lib directory. In other
- * words, the FileCleaner class is loaded through the class loader of your
- * web application. If the web application is terminated, but the servlet
- * container is still running, then the file cleaner thread will still exist,
- * posing a memory leak.
- * <p>
- * This method allows the thread to be terminated. Simply call this method
- * in the resource cleanup code, such as {@link javax.servlet.ServletContextListener#contextDestroyed}.
- * One called, no new objects can be tracked by the file cleaner.
- * @deprecated Use {@link FileCleaningTracker#exitWhenFinished()}.
- */
- public static synchronized void exitWhenFinished() {
- theInstance.exitWhenFinished();
- }
-
- /**
- * Returns the singleton instance, which is used by the deprecated, static methods.
- * This is mainly useful for code, which wants to support the new
- * {@link FileCleaningTracker} class while maintain compatibility with the
- * deprecated {@link FileCleaner}.
- *
- * @return the singleton instance
- */
- public static FileCleaningTracker getInstance() {
- return theInstance;
- }
-}
diff --git a/src/org/apache/commons/io/FileCleaningTracker.java b/src/org/apache/commons/io/FileCleaningTracker.java
deleted file mode 100644
index ea976d60a..000000000
--- a/src/org/apache/commons/io/FileCleaningTracker.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io;
-
-import java.io.File;
-import java.lang.ref.PhantomReference;
-import java.lang.ref.ReferenceQueue;
-import java.util.Collection;
-import java.util.Vector;
-
-/**
- * Keeps track of files awaiting deletion, and deletes them when an associated
- * marker object is reclaimed by the garbage collector.
- * <p>
- * This utility creates a background thread to handle file deletion.
- * Each file to be deleted is registered with a handler object.
- * When the handler object is garbage collected, the file is deleted.
- * <p>
- * In an environment with multiple class loaders (a servlet container, for
- * example), you should consider stopping the background thread if it is no
- * longer needed. This is done by invoking the method
- * {@link #exitWhenFinished}, typically in
- * {@link javax.servlet.ServletContextListener#contextDestroyed} or similar.
- *
- * @author Noel Bergman
- * @author Martin Cooper
- * @version $Id: FileCleaner.java 490987 2006-12-29 12:11:48Z scolebourne $
- */
-public class FileCleaningTracker {
- /**
- * Queue of <code>Tracker</code> instances being watched.
- */
- ReferenceQueue /* Tracker */ q = new ReferenceQueue();
- /**
- * Collection of <code>Tracker</code> instances in existence.
- */
- final Collection /* Tracker */ trackers = new Vector(); // synchronized
- /**
- * Whether to terminate the thread when the tracking is complete.
- */
- volatile boolean exitWhenFinished = false;
- /**
- * The thread that will clean up registered files.
- */
- Thread reaper;
-
- //-----------------------------------------------------------------------
- /**
- * Track the specified file, using the provided marker, deleting the file
- * when the marker instance is garbage collected.
- * The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used.
- *
- * @param file the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @throws NullPointerException if the file is null
- */
- public void track(File file, Object marker) {
- track(file, marker, (FileDeleteStrategy) null);
- }
-
- /**
- * Track the specified file, using the provided marker, deleting the file
- * when the marker instance is garbage collected.
- * The speified deletion strategy is used.
- *
- * @param file the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @param deleteStrategy the strategy to delete the file, null means normal
- * @throws NullPointerException if the file is null
- */
- public void track(File file, Object marker, FileDeleteStrategy deleteStrategy) {
- if (file == null) {
- throw new NullPointerException("The file must not be null");
- }
- addTracker(file.getPath(), marker, deleteStrategy);
- }
-
- /**
- * Track the specified file, using the provided marker, deleting the file
- * when the marker instance is garbage collected.
- * The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used.
- *
- * @param path the full path to the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @throws NullPointerException if the path is null
- */
- public void track(String path, Object marker) {
- track(path, marker, (FileDeleteStrategy) null);
- }
-
- /**
- * Track the specified file, using the provided marker, deleting the file
- * when the marker instance is garbage collected.
- * The speified deletion strategy is used.
- *
- * @param path the full path to the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @param deleteStrategy the strategy to delete the file, null means normal
- * @throws NullPointerException if the path is null
- */
- public void track(String path, Object marker, FileDeleteStrategy deleteStrategy) {
- if (path == null) {
- throw new NullPointerException("The path must not be null");
- }
- addTracker(path, marker, deleteStrategy);
- }
-
- /**
- * Adds a tracker to the list of trackers.
- *
- * @param path the full path to the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @param deleteStrategy the strategy to delete the file, null means normal
- */
- private synchronized void addTracker(String path, Object marker, FileDeleteStrategy deleteStrategy) {
- // synchronized block protects reaper
- if (exitWhenFinished) {
- throw new IllegalStateException("No new trackers can be added once exitWhenFinished() is called");
- }
- if (reaper == null) {
- reaper = new Reaper();
- reaper.start();
- }
- trackers.add(new Tracker(path, deleteStrategy, marker, q));
- }
-
- //-----------------------------------------------------------------------
- /**
- * Retrieve the number of files currently being tracked, and therefore
- * awaiting deletion.
- *
- * @return the number of files being tracked
- */
- public int getTrackCount() {
- return trackers.size();
- }
-
- /**
- * Call this method to cause the file cleaner thread to terminate when
- * there are no more objects being tracked for deletion.
- * <p>
- * In a simple environment, you don't need this method as the file cleaner
- * thread will simply exit when the JVM exits. In a more complex environment,
- * with multiple class loaders (such as an application server), you should be
- * aware that the file cleaner thread will continue running even if the class
- * loader it was started from terminates. This can consitute a memory leak.
- * <p>
- * For example, suppose that you have developed a web application, which
- * contains the commons-io jar file in your WEB-INF/lib directory. In other
- * words, the FileCleaner class is loaded through the class loader of your
- * web application. If the web application is terminated, but the servlet
- * container is still running, then the file cleaner thread will still exist,
- * posing a memory leak.
- * <p>
- * This method allows the thread to be terminated. Simply call this method
- * in the resource cleanup code, such as {@link javax.servlet.ServletContextListener#contextDestroyed}.
- * One called, no new objects can be tracked by the file cleaner.
- */
- public synchronized void exitWhenFinished() {
- // synchronized block protects reaper
- exitWhenFinished = true;
- if (reaper != null) {
- synchronized (reaper) {
- reaper.interrupt();
- }
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * The reaper thread.
- */
- private final class Reaper extends Thread {
- /** Construct a new Reaper */
- Reaper() {
- super("File Reaper");
- setPriority(Thread.MAX_PRIORITY);
- setDaemon(true);
- }
-
- /**
- * Run the reaper thread that will delete files as their associated
- * marker objects are reclaimed by the garbage collector.
- */
- public void run() {
- // thread exits when exitWhenFinished is true and there are no more tracked objects
- while (exitWhenFinished == false || trackers.size() > 0) {
- Tracker tracker = null;
- try {
- // Wait for a tracker to remove.
- tracker = (Tracker) q.remove();
- } catch (Exception e) {
- continue;
- }
- if (tracker != null) {
- tracker.delete();
- tracker.clear();
- trackers.remove(tracker);
- }
- }
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Inner class which acts as the reference for a file pending deletion.
- */
- private static final class Tracker extends PhantomReference {
-
- /**
- * The full path to the file being tracked.
- */
- private final String path;
- /**
- * The strategy for deleting files.
- */
- private final FileDeleteStrategy deleteStrategy;
-
- /**
- * Constructs an instance of this class from the supplied parameters.
- *
- * @param path the full path to the file to be tracked, not null
- * @param deleteStrategy the strategy to delete the file, null means normal
- * @param marker the marker object used to track the file, not null
- * @param queue the queue on to which the tracker will be pushed, not null
- */
- Tracker(String path, FileDeleteStrategy deleteStrategy, Object marker, ReferenceQueue queue) {
- super(marker, queue);
- this.path = path;
- this.deleteStrategy = (deleteStrategy == null ? FileDeleteStrategy.NORMAL : deleteStrategy);
- }
-
- /**
- * Deletes the file associated with this tracker instance.
- *
- * @return <code>true</code> if the file was deleted successfully;
- * <code>false</code> otherwise.
- */
- public boolean delete() {
- return deleteStrategy.deleteQuietly(new File(path));
- }
- }
-
-}
diff --git a/src/org/apache/commons/io/FileDeleteStrategy.java b/src/org/apache/commons/io/FileDeleteStrategy.java
deleted file mode 100644
index 8b6b4b9aa..000000000
--- a/src/org/apache/commons/io/FileDeleteStrategy.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io;
-
-import java.io.File;
-import java.io.IOException;
-
-/**
- * Strategy for deleting files.
- * <p>
- * There is more than one way to delete a file.
- * You may want to limit access to certain directories, to only delete
- * directories if they are empty, or maybe to force deletion.
- * <p>
- * This class captures the strategy to use and is designed for user subclassing.
- *
- * @author Stephen Colebourne
- * @version $Id: FileDeleteStrategy.java 453903 2006-10-07 13:47:06Z scolebourne $
- * @since Commons IO 1.3
- */
-public class FileDeleteStrategy {
-
- /**
- * The singleton instance for normal file deletion, which does not permit
- * the deletion of directories that are not empty.
- */
- public static final FileDeleteStrategy NORMAL = new FileDeleteStrategy("Normal");
- /**
- * The singleton instance for forced file deletion, which always deletes,
- * even if the file represents a non-empty directory.
- */
- public static final FileDeleteStrategy FORCE = new ForceFileDeleteStrategy();
-
- /** The name of the strategy. */
- private final String name;
-
- //-----------------------------------------------------------------------
- /**
- * Restricted constructor.
- *
- * @param name the name by which the strategy is known
- */
- protected FileDeleteStrategy(String name) {
- this.name = name;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Deletes the file object, which may be a file or a directory.
- * All <code>IOException</code>s are caught and false returned instead.
- * If the file does not exist or is null, true is returned.
- * <p>
- * Subclass writers should override {@link #doDelete(File)}, not this method.
- *
- * @param fileToDelete the file to delete, null returns true
- * @return true if the file was deleted, or there was no such file
- */
- public boolean deleteQuietly(File fileToDelete) {
- if (fileToDelete == null || fileToDelete.exists() == false) {
- return true;
- }
- try {
- return doDelete(fileToDelete);
- } catch (IOException ex) {
- return false;
- }
- }
-
- /**
- * Deletes the file object, which may be a file or a directory.
- * If the file does not exist, the method just returns.
- * <p>
- * Subclass writers should override {@link #doDelete(File)}, not this method.
- *
- * @param fileToDelete the file to delete, not null
- * @throws NullPointerException if the file is null
- * @throws IOException if an error occurs during file deletion
- */
- public void delete(File fileToDelete) throws IOException {
- if (fileToDelete.exists() && doDelete(fileToDelete) == false) {
- throw new IOException("Deletion failed: " + fileToDelete);
- }
- }
-
- /**
- * Actually deletes the file object, which may be a file or a directory.
- * <p>
- * This method is designed for subclasses to override.
- * The implementation may return either false or an <code>IOException</code>
- * when deletion fails. The {@link #delete(File)} and {@link #deleteQuietly(File)}
- * methods will handle either response appropriately.
- * A check has been made to ensure that the file will exist.
- * <p>
- * This implementation uses {@link File#delete()}.
- *
- * @param fileToDelete the file to delete, exists, not null
- * @return true if the file was deleteds
- * @throws NullPointerException if the file is null
- * @throws IOException if an error occurs during file deletion
- */
- protected boolean doDelete(File fileToDelete) throws IOException {
- return fileToDelete.delete();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets a string describing the delete strategy.
- *
- * @return a string describing the delete strategy
- */
- public String toString() {
- return "FileDeleteStrategy[" + name + "]";
- }
-
- //-----------------------------------------------------------------------
- /**
- * Force file deletion strategy.
- */
- static class ForceFileDeleteStrategy extends FileDeleteStrategy {
- /** Default Constructor */
- ForceFileDeleteStrategy() {
- super("Force");
- }
-
- /**
- * Deletes the file object.
- * <p>
- * This implementation uses <code>FileUtils.forceDelete() <code>
- * if the file exists.
- *
- * @param fileToDelete the file to delete, not null
- * @return Always returns <code>true</code>
- * @throws NullPointerException if the file is null
- * @throws IOException if an error occurs during file deletion
- */
- protected boolean doDelete(File fileToDelete) throws IOException {
- FileUtils.forceDelete(fileToDelete);
- return true;
- }
- }
-
-}
diff --git a/src/org/apache/commons/io/FileSystemUtils.java b/src/org/apache/commons/io/FileSystemUtils.java
deleted file mode 100644
index a29dba439..000000000
--- a/src/org/apache/commons/io/FileSystemUtils.java
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.StringTokenizer;
-
-/**
- * General File System utilities.
- * <p>
- * This class provides static utility methods for general file system
- * functions not provided via the JDK {@link java.io.File File} class.
- * <p>
- * The current functions provided are:
- * <ul>
- * <li>Get the free space on a drive
- * </ul>
- *
- * @author Frank W. Zammetti
- * @author Stephen Colebourne
- * @author Thomas Ledoux
- * @author James Urie
- * @author Magnus Grimsell
- * @author Thomas Ledoux
- * @version $Id: FileSystemUtils.java 453889 2006-10-07 11:56:25Z scolebourne $
- * @since Commons IO 1.1
- */
-public class FileSystemUtils {
-
- /** Singleton instance, used mainly for testing. */
- private static final FileSystemUtils INSTANCE = new FileSystemUtils();
-
- /** Operating system state flag for error. */
- private static final int INIT_PROBLEM = -1;
- /** Operating system state flag for neither Unix nor Windows. */
- private static final int OTHER = 0;
- /** Operating system state flag for Windows. */
- private static final int WINDOWS = 1;
- /** Operating system state flag for Unix. */
- private static final int UNIX = 2;
- /** Operating system state flag for Posix flavour Unix. */
- private static final int POSIX_UNIX = 3;
-
- /** The operating system flag. */
- private static final int OS;
- static {
- int os = OTHER;
- try {
- String osName = System.getProperty("os.name");
- if (osName == null) {
- throw new IOException("os.name not found");
- }
- osName = osName.toLowerCase();
- // match
- if (osName.indexOf("windows") != -1) {
- os = WINDOWS;
- } else if (osName.indexOf("linux") != -1 ||
- osName.indexOf("sun os") != -1 ||
- osName.indexOf("sunos") != -1 ||
- osName.indexOf("solaris") != -1 ||
- osName.indexOf("mpe/ix") != -1 ||
- osName.indexOf("freebsd") != -1 ||
- osName.indexOf("irix") != -1 ||
- osName.indexOf("digital unix") != -1 ||
- osName.indexOf("unix") != -1 ||
- osName.indexOf("mac os x") != -1) {
- os = UNIX;
- } else if (osName.indexOf("hp-ux") != -1 ||
- osName.indexOf("aix") != -1) {
- os = POSIX_UNIX;
- } else {
- os = OTHER;
- }
-
- } catch (Exception ex) {
- os = INIT_PROBLEM;
- }
- OS = os;
- }
-
- /**
- * Instances should NOT be constructed in standard programming.
- */
- public FileSystemUtils() {
- super();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Returns the free space on a drive or volume by invoking
- * the command line.
- * This method does not normalize the result, and typically returns
- * bytes on Windows, 512 byte units on OS X and kilobytes on Unix.
- * As this is not very useful, this method is deprecated in favour
- * of {@link #freeSpaceKb(String)} which returns a result in kilobytes.
- * <p>
- * Note that some OS's are NOT currently supported, including OS/390,
- * OpenVMS and and SunOS 5. (SunOS is supported by <code>freeSpaceKb</code>.)
- * <pre>
- * FileSystemUtils.freeSpace("C:"); // Windows
- * FileSystemUtils.freeSpace("/volume"); // *nix
- * </pre>
- * The free space is calculated via the command line.
- * It uses 'dir /-c' on Windows and 'df' on *nix.
- *
- * @param path the path to get free space for, not null, not empty on Unix
- * @return the amount of free drive space on the drive or volume
- * @throws IllegalArgumentException if the path is invalid
- * @throws IllegalStateException if an error occurred in initialisation
- * @throws IOException if an error occurs when finding the free space
- * @since Commons IO 1.1, enhanced OS support in 1.2 and 1.3
- * @deprecated Use freeSpaceKb(String)
- * Deprecated from 1.3, may be removed in 2.0
- */
- public static long freeSpace(String path) throws IOException {
- return INSTANCE.freeSpaceOS(path, OS, false);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Returns the free space on a drive or volume in kilobytes by invoking
- * the command line.
- * <pre>
- * FileSystemUtils.freeSpaceKb("C:"); // Windows
- * FileSystemUtils.freeSpaceKb("/volume"); // *nix
- * </pre>
- * The free space is calculated via the command line.
- * It uses 'dir /-c' on Windows, 'df -kP' on AIX/HP-UX and 'df -k' on other Unix.
- * <p>
- * In order to work, you must be running Windows, or have a implementation of
- * Unix df that supports GNU format when passed -k (or -kP). If you are going
- * to rely on this code, please check that it works on your OS by running
- * some simple tests to compare the command line with the output from this class.
- * If your operating system isn't supported, please raise a JIRA call detailing
- * the exact result from df -k and as much other detail as possible, thanks.
- *
- * @param path the path to get free space for, not null, not empty on Unix
- * @return the amount of free drive space on the drive or volume in kilobytes
- * @throws IllegalArgumentException if the path is invalid
- * @throws IllegalStateException if an error occurred in initialisation
- * @throws IOException if an error occurs when finding the free space
- * @since Commons IO 1.2, enhanced OS support in 1.3
- */
- public static long freeSpaceKb(String path) throws IOException {
- return INSTANCE.freeSpaceOS(path, OS, true);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Returns the free space on a drive or volume in a cross-platform manner.
- * Note that some OS's are NOT currently supported, including OS/390.
- * <pre>
- * FileSystemUtils.freeSpace("C:"); // Windows
- * FileSystemUtils.freeSpace("/volume"); // *nix
- * </pre>
- * The free space is calculated via the command line.
- * It uses 'dir /-c' on Windows and 'df' on *nix.
- *
- * @param path the path to get free space for, not null, not empty on Unix
- * @param os the operating system code
- * @param kb whether to normalize to kilobytes
- * @return the amount of free drive space on the drive or volume
- * @throws IllegalArgumentException if the path is invalid
- * @throws IllegalStateException if an error occurred in initialisation
- * @throws IOException if an error occurs when finding the free space
- */
- long freeSpaceOS(String path, int os, boolean kb) throws IOException {
- if (path == null) {
- throw new IllegalArgumentException("Path must not be empty");
- }
- switch (os) {
- case WINDOWS:
- return (kb ? freeSpaceWindows(path) / 1024 : freeSpaceWindows(path));
- case UNIX:
- return freeSpaceUnix(path, kb, false);
- case POSIX_UNIX:
- return freeSpaceUnix(path, kb, true);
- case OTHER:
- throw new IllegalStateException("Unsupported operating system");
- default:
- throw new IllegalStateException(
- "Exception caught when determining operating system");
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Find free space on the Windows platform using the 'dir' command.
- *
- * @param path the path to get free space for, including the colon
- * @return the amount of free drive space on the drive
- * @throws IOException if an error occurs
- */
- long freeSpaceWindows(String path) throws IOException {
- path = FilenameUtils.normalize(path);
- if (path.length() > 2 && path.charAt(1) == ':') {
- path = path.substring(0, 2); // seems to make it work
- }
-
- // build and run the 'dir' command
- String[] cmdAttribs = new String[] {"cmd.exe", "/C", "dir /-c " + path};
-
- // read in the output of the command to an ArrayList
- List lines = performCommand(cmdAttribs, Integer.MAX_VALUE);
-
- // now iterate over the lines we just read and find the LAST
- // non-empty line (the free space bytes should be in the last element
- // of the ArrayList anyway, but this will ensure it works even if it's
- // not, still assuming it is on the last non-blank line)
- for (int i = lines.size() - 1; i >= 0; i--) {
- String line = (String) lines.get(i);
- if (line.length() > 0) {
- return parseDir(line, path);
- }
- }
- // all lines are blank
- throw new IOException(
- "Command line 'dir /-c' did not return any info " +
- "for path '" + path + "'");
- }
-
- /**
- * Parses the Windows dir response last line
- *
- * @param line the line to parse
- * @param path the path that was sent
- * @return the number of bytes
- * @throws IOException if an error occurs
- */
- long parseDir(String line, String path) throws IOException {
- // read from the end of the line to find the last numeric
- // character on the line, then continue until we find the first
- // non-numeric character, and everything between that and the last
- // numeric character inclusive is our free space bytes count
- int bytesStart = 0;
- int bytesEnd = 0;
- int j = line.length() - 1;
- innerLoop1: while (j >= 0) {
- char c = line.charAt(j);
- if (Character.isDigit(c)) {
- // found the last numeric character, this is the end of
- // the free space bytes count
- bytesEnd = j + 1;
- break innerLoop1;
- }
- j--;
- }
- innerLoop2: while (j >= 0) {
- char c = line.charAt(j);
- if (!Character.isDigit(c) && c != ',' && c != '.') {
- // found the next non-numeric character, this is the
- // beginning of the free space bytes count
- bytesStart = j + 1;
- break innerLoop2;
- }
- j--;
- }
- if (j < 0) {
- throw new IOException(
- "Command line 'dir /-c' did not return valid info " +
- "for path '" + path + "'");
- }
-
- // remove commas and dots in the bytes count
- StringBuffer buf = new StringBuffer(line.substring(bytesStart, bytesEnd));
- for (int k = 0; k < buf.length(); k++) {
- if (buf.charAt(k) == ',' || buf.charAt(k) == '.') {
- buf.deleteCharAt(k--);
- }
- }
- return parseBytes(buf.toString(), path);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Find free space on the *nix platform using the 'df' command.
- *
- * @param path the path to get free space for
- * @param kb whether to normalize to kilobytes
- * @param posix whether to use the posix standard format flag
- * @return the amount of free drive space on the volume
- * @throws IOException if an error occurs
- */
- long freeSpaceUnix(String path, boolean kb, boolean posix) throws IOException {
- if (path.length() == 0) {
- throw new IllegalArgumentException("Path must not be empty");
- }
- path = FilenameUtils.normalize(path);
-
- // build and run the 'dir' command
- String flags = "-";
- if (kb) {
- flags += "k";
- }
- if (posix) {
- flags += "P";
- }
- String[] cmdAttribs =
- (flags.length() > 1 ? new String[] {"df", flags, path} : new String[] {"df", path});
-
- // perform the command, asking for up to 3 lines (header, interesting, overflow)
- List lines = performCommand(cmdAttribs, 3);
- if (lines.size() < 2) {
- // unknown problem, throw exception
- throw new IOException(
- "Command line 'df' did not return info as expected " +
- "for path '" + path + "'- response was " + lines);
- }
- String line2 = (String) lines.get(1); // the line we're interested in
-
- // Now, we tokenize the string. The fourth element is what we want.
- StringTokenizer tok = new StringTokenizer(line2, " ");
- if (tok.countTokens() < 4) {
- // could be long Filesystem, thus data on third line
- if (tok.countTokens() == 1 && lines.size() >= 3) {
- String line3 = (String) lines.get(2); // the line may be interested in
- tok = new StringTokenizer(line3, " ");
- } else {
- throw new IOException(
- "Command line 'df' did not return data as expected " +
- "for path '" + path + "'- check path is valid");
- }
- } else {
- tok.nextToken(); // Ignore Filesystem
- }
- tok.nextToken(); // Ignore 1K-blocks
- tok.nextToken(); // Ignore Used
- String freeSpace = tok.nextToken();
- return parseBytes(freeSpace, path);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Parses the bytes from a string.
- *
- * @param freeSpace the free space string
- * @param path the path
- * @return the number of bytes
- * @throws IOException if an error occurs
- */
- long parseBytes(String freeSpace, String path) throws IOException {
- try {
- long bytes = Long.parseLong(freeSpace);
- if (bytes < 0) {
- throw new IOException(
- "Command line 'df' did not find free space in response " +
- "for path '" + path + "'- check path is valid");
- }
- return bytes;
-
- } catch (NumberFormatException ex) {
- throw new IOException(
- "Command line 'df' did not return numeric data as expected " +
- "for path '" + path + "'- check path is valid");
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Performs the os command.
- *
- * @param cmdAttribs the command line parameters
- * @param max The maximum limit for the lines returned
- * @return the parsed data
- * @throws IOException if an error occurs
- */
- List performCommand(String[] cmdAttribs, int max) throws IOException {
- // this method does what it can to avoid the 'Too many open files' error
- // based on trial and error and these links:
- // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4784692
- // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4801027
- // http://forum.java.sun.com/thread.jspa?threadID=533029&messageID=2572018
- // however, its still not perfect as the JDK support is so poor
- // (see commond-exec or ant for a better multi-threaded multi-os solution)
-
- List lines = new ArrayList(20);
- Process proc = null;
- InputStream in = null;
- OutputStream out = null;
- InputStream err = null;
- BufferedReader inr = null;
- try {
- proc = openProcess(cmdAttribs);
- in = proc.getInputStream();
- out = proc.getOutputStream();
- err = proc.getErrorStream();
- inr = new BufferedReader(new InputStreamReader(in));
- String line = inr.readLine();
- while (line != null && lines.size() < max) {
- line = line.toLowerCase().trim();
- lines.add(line);
- line = inr.readLine();
- }
-
- proc.waitFor();
- if (proc.exitValue() != 0) {
- // os command problem, throw exception
- throw new IOException(
- "Command line returned OS error code '" + proc.exitValue() +
- "' for command " + Arrays.asList(cmdAttribs));
- }
- if (lines.size() == 0) {
- // unknown problem, throw exception
- throw new IOException(
- "Command line did not return any info " +
- "for command " + Arrays.asList(cmdAttribs));
- }
- return lines;
-
- } catch (InterruptedException ex) {
- throw new IOException(
- "Command line threw an InterruptedException '" + ex.getMessage() +
- "' for command " + Arrays.asList(cmdAttribs));
- } finally {
- IOUtils.closeQuietly(in);
- IOUtils.closeQuietly(out);
- IOUtils.closeQuietly(err);
- IOUtils.closeQuietly(inr);
- if (proc != null) {
- proc.destroy();
- }
- }
- }
-
- /**
- * Opens the process to the operating system.
- *
- * @param cmdAttribs the command line parameters
- * @return the process
- * @throws IOException if an error occurs
- */
- Process openProcess(String[] cmdAttribs) throws IOException {
- return Runtime.getRuntime().exec(cmdAttribs);
- }
-
-}
diff --git a/src/org/apache/commons/io/FileUtils.java b/src/org/apache/commons/io/FileUtils.java
deleted file mode 100644
index 254800cd1..000000000
--- a/src/org/apache/commons/io/FileUtils.java
+++ /dev/null
@@ -1,1890 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.zip.CRC32;
-import java.util.zip.CheckedInputStream;
-import java.util.zip.Checksum;
-
-import org.apache.commons.io.filefilter.DirectoryFileFilter;
-import org.apache.commons.io.filefilter.FalseFileFilter;
-import org.apache.commons.io.filefilter.FileFilterUtils;
-import org.apache.commons.io.filefilter.IOFileFilter;
-import org.apache.commons.io.filefilter.SuffixFileFilter;
-import org.apache.commons.io.filefilter.TrueFileFilter;
-import org.apache.commons.io.output.NullOutputStream;
-
-/**
- * General file manipulation utilities.
- * <p>
- * Facilities are provided in the following areas:
- * <ul>
- * <li>writing to a file
- * <li>reading from a file
- * <li>make a directory including parent directories
- * <li>copying files and directories
- * <li>deleting files and directories
- * <li>converting to and from a URL
- * <li>listing files and directories by filter and extension
- * <li>comparing file content
- * <li>file last changed date
- * <li>calculating a checksum
- * </ul>
- * <p>
- * Origin of code: Excalibur, Alexandria, Commons-Utils
- *
- * @author <a href="mailto:burton@relativity.yi.org">Kevin A. Burton</A>
- * @author <a href="mailto:sanders@apache.org">Scott Sanders</a>
- * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
- * @author <a href="mailto:Christoph.Reck@dlr.de">Christoph.Reck</a>
- * @author <a href="mailto:peter@apache.org">Peter Donald</a>
- * @author <a href="mailto:jefft@apache.org">Jeff Turner</a>
- * @author Matthew Hawthorne
- * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
- * @author Stephen Colebourne
- * @author Ian Springer
- * @author Chris Eldredge
- * @author Jim Harrington
- * @author Niall Pemberton
- * @author Sandy McArthur
- * @version $Id: FileUtils.java 610810 2008-01-10 15:04:49Z niallp $
- */
-public class FileUtils {
-
- /**
- * Instances should NOT be constructed in standard programming.
- */
- public FileUtils() {
- super();
- }
-
- /**
- * The number of bytes in a kilobyte.
- */
- public static final long ONE_KB = 1024;
-
- /**
- * The number of bytes in a megabyte.
- */
- public static final long ONE_MB = ONE_KB * ONE_KB;
-
- /**
- * The number of bytes in a gigabyte.
- */
- public static final long ONE_GB = ONE_KB * ONE_MB;
-
- /**
- * An empty array of type <code>File</code>.
- */
- public static final File[] EMPTY_FILE_ARRAY = new File[0];
-
- //-----------------------------------------------------------------------
- /**
- * Opens a {@link FileInputStream} for the specified file, providing better
- * error messages than simply calling <code>new FileInputStream(file)</code>.
- * <p>
- * At the end of the method either the stream will be successfully opened,
- * or an exception will have been thrown.
- * <p>
- * An exception is thrown if the file does not exist.
- * An exception is thrown if the file object exists but is a directory.
- * An exception is thrown if the file exists but cannot be read.
- *
- * @param file the file to open for input, must not be <code>null</code>
- * @return a new {@link FileInputStream} for the specified file
- * @throws FileNotFoundException if the file does not exist
- * @throws IOException if the file object is a directory
- * @throws IOException if the file cannot be read
- * @since Commons IO 1.3
- */
- public static FileInputStream openInputStream(File file) throws IOException {
- if (file.exists()) {
- if (file.isDirectory()) {
- throw new IOException("File '" + file + "' exists but is a directory");
- }
- if (file.canRead() == false) {
- throw new IOException("File '" + file + "' cannot be read");
- }
- } else {
- throw new FileNotFoundException("File '" + file + "' does not exist");
- }
- return new FileInputStream(file);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Opens a {@link FileOutputStream} for the specified file, checking and
- * creating the parent directory if it does not exist.
- * <p>
- * At the end of the method either the stream will be successfully opened,
- * or an exception will have been thrown.
- * <p>
- * The parent directory will be created if it does not exist.
- * The file will be created if it does not exist.
- * An exception is thrown if the file object exists but is a directory.
- * An exception is thrown if the file exists but cannot be written to.
- * An exception is thrown if the parent directory cannot be created.
- *
- * @param file the file to open for output, must not be <code>null</code>
- * @return a new {@link FileOutputStream} for the specified file
- * @throws IOException if the file object is a directory
- * @throws IOException if the file cannot be written to
- * @throws IOException if a parent directory needs creating but that fails
- * @since Commons IO 1.3
- */
- public static FileOutputStream openOutputStream(File file) throws IOException {
- if (file.exists()) {
- if (file.isDirectory()) {
- throw new IOException("File '" + file + "' exists but is a directory");
- }
- if (file.canWrite() == false) {
- throw new IOException("File '" + file + "' cannot be written to");
- }
- } else {
- File parent = file.getParentFile();
- if (parent != null && parent.exists() == false) {
- if (parent.mkdirs() == false) {
- throw new IOException("File '" + file + "' could not be created");
- }
- }
- }
- return new FileOutputStream(file);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Returns a human-readable version of the file size, where the input
- * represents a specific number of bytes.
- *
- * @param size the number of bytes
- * @return a human-readable display value (includes units)
- */
- public static String byteCountToDisplaySize(long size) {
- String displaySize;
-
- if (size / ONE_GB > 0) {
- displaySize = String.valueOf(size / ONE_GB) + " GB";
- } else if (size / ONE_MB > 0) {
- displaySize = String.valueOf(size / ONE_MB) + " MB";
- } else if (size / ONE_KB > 0) {
- displaySize = String.valueOf(size / ONE_KB) + " KB";
- } else {
- displaySize = String.valueOf(size) + " bytes";
- }
- return displaySize;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Implements the same behaviour as the "touch" utility on Unix. It creates
- * a new file with size 0 or, if the file exists already, it is opened and
- * closed without modifying it, but updating the file date and time.
- * <p>
- * NOTE: As from v1.3, this method throws an IOException if the last
- * modified date of the file cannot be set. Also, as from v1.3 this method
- * creates parent directories if they do not exist.
- *
- * @param file the File to touch
- * @throws IOException If an I/O problem occurs
- */
- public static void touch(File file) throws IOException {
- if (!file.exists()) {
- OutputStream out = openOutputStream(file);
- IOUtils.closeQuietly(out);
- }
- boolean success = file.setLastModified(System.currentTimeMillis());
- if (!success) {
- throw new IOException("Unable to set the last modification time for " + file);
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Converts a Collection containing java.io.File instanced into array
- * representation. This is to account for the difference between
- * File.listFiles() and FileUtils.listFiles().
- *
- * @param files a Collection containing java.io.File instances
- * @return an array of java.io.File
- */
- public static File[] convertFileCollectionToFileArray(Collection files) {
- return (File[]) files.toArray(new File[files.size()]);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Finds files within a given directory (and optionally its
- * subdirectories). All files found are filtered by an IOFileFilter.
- *
- * @param files the collection of files found.
- * @param directory the directory to search in.
- * @param filter the filter to apply to files and directories.
- */
- private static void innerListFiles(Collection files, File directory,
- IOFileFilter filter) {
- File[] found = directory.listFiles((FileFilter) filter);
- if (found != null) {
- for (int i = 0; i < found.length; i++) {
- if (found[i].isDirectory()) {
- innerListFiles(files, found[i], filter);
- } else {
- files.add(found[i]);
- }
- }
- }
- }
-
- /**
- * Finds files within a given directory (and optionally its
- * subdirectories). All files found are filtered by an IOFileFilter.
- * <p>
- * If your search should recurse into subdirectories you can pass in
- * an IOFileFilter for directories. You don't need to bind a
- * DirectoryFileFilter (via logical AND) to this filter. This method does
- * that for you.
- * <p>
- * An example: If you want to search through all directories called
- * "temp" you pass in <code>FileFilterUtils.NameFileFilter("temp")</code>
- * <p>
- * Another common usage of this method is find files in a directory
- * tree but ignoring the directories generated CVS. You can simply pass
- * in <code>FileFilterUtils.makeCVSAware(null)</code>.
- *
- * @param directory the directory to search in
- * @param fileFilter filter to apply when finding files.
- * @param dirFilter optional filter to apply when finding subdirectories.
- * If this parameter is <code>null</code>, subdirectories will not be included in the
- * search. Use TrueFileFilter.INSTANCE to match all directories.
- * @return an collection of java.io.File with the matching files
- * @see org.apache.commons.io.filefilter.FileFilterUtils
- * @see org.apache.commons.io.filefilter.NameFileFilter
- */
- public static Collection listFiles(
- File directory, IOFileFilter fileFilter, IOFileFilter dirFilter) {
- if (!directory.isDirectory()) {
- throw new IllegalArgumentException(
- "Parameter 'directory' is not a directory");
- }
- if (fileFilter == null) {
- throw new NullPointerException("Parameter 'fileFilter' is null");
- }
-
- //Setup effective file filter
- IOFileFilter effFileFilter = FileFilterUtils.andFileFilter(fileFilter,
- FileFilterUtils.notFileFilter(DirectoryFileFilter.INSTANCE));
-
- //Setup effective directory filter
- IOFileFilter effDirFilter;
- if (dirFilter == null) {
- effDirFilter = FalseFileFilter.INSTANCE;
- } else {
- effDirFilter = FileFilterUtils.andFileFilter(dirFilter,
- DirectoryFileFilter.INSTANCE);
- }
-
- //Find files
- Collection files = new java.util.LinkedList();
- innerListFiles(files, directory,
- FileFilterUtils.orFileFilter(effFileFilter, effDirFilter));
- return files;
- }
-
- /**
- * Allows iteration over the files in given directory (and optionally
- * its subdirectories).
- * <p>
- * All files found are filtered by an IOFileFilter. This method is
- * based on {@link #listFiles(File, IOFileFilter, IOFileFilter)}.
- *
- * @param directory the directory to search in
- * @param fileFilter filter to apply when finding files.
- * @param dirFilter optional filter to apply when finding subdirectories.
- * If this parameter is <code>null</code>, subdirectories will not be included in the
- * search. Use TrueFileFilter.INSTANCE to match all directories.
- * @return an iterator of java.io.File for the matching files
- * @see org.apache.commons.io.filefilter.FileFilterUtils
- * @see org.apache.commons.io.filefilter.NameFileFilter
- * @since Commons IO 1.2
- */
- public static Iterator iterateFiles(
- File directory, IOFileFilter fileFilter, IOFileFilter dirFilter) {
- return listFiles(directory, fileFilter, dirFilter).iterator();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Converts an array of file extensions to suffixes for use
- * with IOFileFilters.
- *
- * @param extensions an array of extensions. Format: {"java", "xml"}
- * @return an array of suffixes. Format: {".java", ".xml"}
- */
- private static String[] toSuffixes(String[] extensions) {
- String[] suffixes = new String[extensions.length];
- for (int i = 0; i < extensions.length; i++) {
- suffixes[i] = "." + extensions[i];
- }
- return suffixes;
- }
-
-
- /**
- * Finds files within a given directory (and optionally its subdirectories)
- * which match an array of extensions.
- *
- * @param directory the directory to search in
- * @param extensions an array of extensions, ex. {"java","xml"}. If this
- * parameter is <code>null</code>, all files are returned.
- * @param recursive if true all subdirectories are searched as well
- * @return an collection of java.io.File with the matching files
- */
- public static Collection listFiles(
- File directory, String[] extensions, boolean recursive) {
- IOFileFilter filter;
- if (extensions == null) {
- filter = TrueFileFilter.INSTANCE;
- } else {
- String[] suffixes = toSuffixes(extensions);
- filter = new SuffixFileFilter(suffixes);
- }
- return listFiles(directory, filter,
- (recursive ? TrueFileFilter.INSTANCE : FalseFileFilter.INSTANCE));
- }
-
- /**
- * Allows iteration over the files in a given directory (and optionally
- * its subdirectories) which match an array of extensions. This method
- * is based on {@link #listFiles(File, String[], boolean)}.
- *
- * @param directory the directory to search in
- * @param extensions an array of extensions, ex. {"java","xml"}. If this
- * parameter is <code>null</code>, all files are returned.
- * @param recursive if true all subdirectories are searched as well
- * @return an iterator of java.io.File with the matching files
- * @since Commons IO 1.2
- */
- public static Iterator iterateFiles(
- File directory, String[] extensions, boolean recursive) {
- return listFiles(directory, extensions, recursive).iterator();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Compares the contents of two files to determine if they are equal or not.
- * <p>
- * This method checks to see if the two files are different lengths
- * or if they point to the same file, before resorting to byte-by-byte
- * comparison of the contents.
- * <p>
- * Code origin: Avalon
- *
- * @param file1 the first file
- * @param file2 the second file
- * @return true if the content of the files are equal or they both don't
- * exist, false otherwise
- * @throws IOException in case of an I/O error
- */
- public static boolean contentEquals(File file1, File file2) throws IOException {
- boolean file1Exists = file1.exists();
- if (file1Exists != file2.exists()) {
- return false;
- }
-
- if (!file1Exists) {
- // two not existing files are equal
- return true;
- }
-
- if (file1.isDirectory() || file2.isDirectory()) {
- // don't want to compare directory contents
- throw new IOException("Can't compare directories, only files");
- }
-
- if (file1.length() != file2.length()) {
- // lengths differ, cannot be equal
- return false;
- }
-
- if (file1.getCanonicalFile().equals(file2.getCanonicalFile())) {
- // same file
- return true;
- }
-
- InputStream input1 = null;
- InputStream input2 = null;
- try {
- input1 = new FileInputStream(file1);
- input2 = new FileInputStream(file2);
- return IOUtils.contentEquals(input1, input2);
-
- } finally {
- IOUtils.closeQuietly(input1);
- IOUtils.closeQuietly(input2);
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Convert from a <code>URL</code> to a <code>File</code>.
- * <p>
- * From version 1.1 this method will decode the URL.
- * Syntax such as <code>file:///my%20docs/file.txt</code> will be
- * correctly decoded to <code>/my docs/file.txt</code>.
- *
- * @param url the file URL to convert, <code>null</code> returns <code>null</code>
- * @return the equivalent <code>File</code> object, or <code>null</code>
- * if the URL's protocol is not <code>file</code>
- * @throws IllegalArgumentException if the file is incorrectly encoded
- */
- public static File toFile(URL url) {
- if (url == null || !url.getProtocol().equals("file")) {
- return null;
- } else {
- String filename = url.getFile().replace('/', File.separatorChar);
- int pos =0;
- while ((pos = filename.indexOf('%', pos)) >= 0) {
- if (pos + 2 < filename.length()) {
- String hexStr = filename.substring(pos + 1, pos + 3);
- char ch = (char) Integer.parseInt(hexStr, 16);
- filename = filename.substring(0, pos) + ch + filename.substring(pos + 3);
- }
- }
- return new File(filename);
- }
- }
-
- /**
- * Converts each of an array of <code>URL</code> to a <code>File</code>.
- * <p>
- * Returns an array of the same size as the input.
- * If the input is <code>null</code>, an empty array is returned.
- * If the input contains <code>null</code>, the output array contains <code>null</code> at the same
- * index.
- * <p>
- * This method will decode the URL.
- * Syntax such as <code>file:///my%20docs/file.txt</code> will be
- * correctly decoded to <code>/my docs/file.txt</code>.
- *
- * @param urls the file URLs to convert, <code>null</code> returns empty array
- * @return a non-<code>null</code> array of Files matching the input, with a <code>null</code> item
- * if there was a <code>null</code> at that index in the input array
- * @throws IllegalArgumentException if any file is not a URL file
- * @throws IllegalArgumentException if any file is incorrectly encoded
- * @since Commons IO 1.1
- */
- public static File[] toFiles(URL[] urls) {
- if (urls == null || urls.length == 0) {
- return EMPTY_FILE_ARRAY;
- }
- File[] files = new File[urls.length];
- for (int i = 0; i < urls.length; i++) {
- URL url = urls[i];
- if (url != null) {
- if (url.getProtocol().equals("file") == false) {
- throw new IllegalArgumentException(
- "URL could not be converted to a File: " + url);
- }
- files[i] = toFile(url);
- }
- }
- return files;
- }
-
- /**
- * Converts each of an array of <code>File</code> to a <code>URL</code>.
- * <p>
- * Returns an array of the same size as the input.
- *
- * @param files the files to convert
- * @return an array of URLs matching the input
- * @throws IOException if a file cannot be converted
- */
- public static URL[] toURLs(File[] files) throws IOException {
- URL[] urls = new URL[files.length];
-
- for (int i = 0; i < urls.length; i++) {
- urls[i] = files[i].toURL();
- }
-
- return urls;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Copies a file to a directory preserving the file date.
- * <p>
- * This method copies the contents of the specified source file
- * to a file of the same name in the specified destination directory.
- * The destination directory is created if it does not exist.
- * If the destination file exists, then this method will overwrite it.
- *
- * @param srcFile an existing file to copy, must not be <code>null</code>
- * @param destDir the directory to place the copy in, must not be <code>null</code>
- *
- * @throws NullPointerException if source or destination is null
- * @throws IOException if source or destination is invalid
- * @throws IOException if an IO error occurs during copying
- * @see #copyFile(File, File, boolean)
- */
- public static void copyFileToDirectory(File srcFile, File destDir) throws IOException {
- copyFileToDirectory(srcFile, destDir, true);
- }
-
- /**
- * Copies a file to a directory optionally preserving the file date.
- * <p>
- * This method copies the contents of the specified source file
- * to a file of the same name in the specified destination directory.
- * The destination directory is created if it does not exist.
- * If the destination file exists, then this method will overwrite it.
- *
- * @param srcFile an existing file to copy, must not be <code>null</code>
- * @param destDir the directory to place the copy in, must not be <code>null</code>
- * @param preserveFileDate true if the file date of the copy
- * should be the same as the original
- *
- * @throws NullPointerException if source or destination is <code>null</code>
- * @throws IOException if source or destination is invalid
- * @throws IOException if an IO error occurs during copying
- * @see #copyFile(File, File, boolean)
- * @since Commons IO 1.3
- */
- public static void copyFileToDirectory(File srcFile, File destDir, boolean preserveFileDate) throws IOException {
- if (destDir == null) {
- throw new NullPointerException("Destination must not be null");
- }
- if (destDir.exists() && destDir.isDirectory() == false) {
- throw new IllegalArgumentException("Destination '" + destDir + "' is not a directory");
- }
- copyFile(srcFile, new File(destDir, srcFile.getName()), preserveFileDate);
- }
-
- /**
- * Copies a file to a new location preserving the file date.
- * <p>
- * This method copies the contents of the specified source file to the
- * specified destination file. The directory holding the destination file is
- * created if it does not exist. If the destination file exists, then this
- * method will overwrite it.
- *
- * @param srcFile an existing file to copy, must not be <code>null</code>
- * @param destFile the new file, must not be <code>null</code>
- *
- * @throws NullPointerException if source or destination is <code>null</code>
- * @throws IOException if source or destination is invalid
- * @throws IOException if an IO error occurs during copying
- * @see #copyFileToDirectory(File, File)
- */
- public static void copyFile(File srcFile, File destFile) throws IOException {
- copyFile(srcFile, destFile, true);
- }
-
- /**
- * Copies a file to a new location.
- * <p>
- * This method copies the contents of the specified source file
- * to the specified destination file.
- * The directory holding the destination file is created if it does not exist.
- * If the destination file exists, then this method will overwrite it.
- *
- * @param srcFile an existing file to copy, must not be <code>null</code>
- * @param destFile the new file, must not be <code>null</code>
- * @param preserveFileDate true if the file date of the copy
- * should be the same as the original
- *
- * @throws NullPointerException if source or destination is <code>null</code>
- * @throws IOException if source or destination is invalid
- * @throws IOException if an IO error occurs during copying
- * @see #copyFileToDirectory(File, File, boolean)
- */
- public static void copyFile(File srcFile, File destFile,
- boolean preserveFileDate) throws IOException {
- if (srcFile == null) {
- throw new NullPointerException("Source must not be null");
- }
- if (destFile == null) {
- throw new NullPointerException("Destination must not be null");
- }
- if (srcFile.exists() == false) {
- throw new FileNotFoundException("Source '" + srcFile + "' does not exist");
- }
- if (srcFile.isDirectory()) {
- throw new IOException("Source '" + srcFile + "' exists but is a directory");
- }
- if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath())) {
- throw new IOException("Source '" + srcFile + "' and destination '" + destFile + "' are the same");
- }
- if (destFile.getParentFile() != null && destFile.getParentFile().exists() == false) {
- if (destFile.getParentFile().mkdirs() == false) {
- throw new IOException("Destination '" + destFile + "' directory cannot be created");
- }
- }
- if (destFile.exists() && destFile.canWrite() == false) {
- throw new IOException("Destination '" + destFile + "' exists but is read-only");
- }
- doCopyFile(srcFile, destFile, preserveFileDate);
- }
-
- /**
- * Internal copy file method.
- *
- * @param srcFile the validated source file, must not be <code>null</code>
- * @param destFile the validated destination file, must not be <code>null</code>
- * @param preserveFileDate whether to preserve the file date
- * @throws IOException if an error occurs
- */
- private static void doCopyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException {
- if (destFile.exists() && destFile.isDirectory()) {
- throw new IOException("Destination '" + destFile + "' exists but is a directory");
- }
-
- FileInputStream input = new FileInputStream(srcFile);
- try {
- FileOutputStream output = new FileOutputStream(destFile);
- try {
- IOUtils.copy(input, output);
- } finally {
- IOUtils.closeQuietly(output);
- }
- } finally {
- IOUtils.closeQuietly(input);
- }
-
- if (srcFile.length() != destFile.length()) {
- throw new IOException("Failed to copy full contents from '" +
- srcFile + "' to '" + destFile + "'");
- }
- if (preserveFileDate) {
- destFile.setLastModified(srcFile.lastModified());
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Copies a directory to within another directory preserving the file dates.
- * <p>
- * This method copies the source directory and all its contents to a
- * directory of the same name in the specified destination directory.
- * <p>
- * The destination directory is created if it does not exist.
- * If the destination directory did exist, then this method merges
- * the source with the destination, with the source taking precedence.
- *
- * @param srcDir an existing directory to copy, must not be <code>null</code>
- * @param destDir the directory to place the copy in, must not be <code>null</code>
- *
- * @throws NullPointerException if source or destination is <code>null</code>
- * @throws IOException if source or destination is invalid
- * @throws IOException if an IO error occurs during copying
- * @since Commons IO 1.2
- */
- public static void copyDirectoryToDirectory(File srcDir, File destDir) throws IOException {
- if (srcDir == null) {
- throw new NullPointerException("Source must not be null");
- }
- if (srcDir.exists() && srcDir.isDirectory() == false) {
- throw new IllegalArgumentException("Source '" + destDir + "' is not a directory");
- }
- if (destDir == null) {
- throw new NullPointerException("Destination must not be null");
- }
- if (destDir.exists() && destDir.isDirectory() == false) {
- throw new IllegalArgumentException("Destination '" + destDir + "' is not a directory");
- }
- copyDirectory(srcDir, new File(destDir, srcDir.getName()), true);
- }
-
- /**
- * Copies a whole directory to a new location preserving the file dates.
- * <p>
- * This method copies the specified directory and all its child
- * directories and files to the specified destination.
- * The destination is the new location and name of the directory.
- * <p>
- * The destination directory is created if it does not exist.
- * If the destination directory did exist, then this method merges
- * the source with the destination, with the source taking precedence.
- *
- * @param srcDir an existing directory to copy, must not be <code>null</code>
- * @param destDir the new directory, must not be <code>null</code>
- *
- * @throws NullPointerException if source or destination is <code>null</code>
- * @throws IOException if source or destination is invalid
- * @throws IOException if an IO error occurs during copying
- * @since Commons IO 1.1
- */
- public static void copyDirectory(File srcDir, File destDir) throws IOException {
- copyDirectory(srcDir, destDir, true);
- }
-
- /**
- * Copies a whole directory to a new location.
- * <p>
- * This method copies the contents of the specified source directory
- * to within the specified destination directory.
- * <p>
- * The destination directory is created if it does not exist.
- * If the destination directory did exist, then this method merges
- * the source with the destination, with the source taking precedence.
- *
- * @param srcDir an existing directory to copy, must not be <code>null</code>
- * @param destDir the new directory, must not be <code>null</code>
- * @param preserveFileDate true if the file date of the copy
- * should be the same as the original
- *
- * @throws NullPointerException if source or destination is <code>null</code>
- * @throws IOException if source or destination is invalid
- * @throws IOException if an IO error occurs during copying
- * @since Commons IO 1.1
- */
- public static void copyDirectory(File srcDir, File destDir,
- boolean preserveFileDate) throws IOException {
- copyDirectory(srcDir, destDir, null, preserveFileDate);
- }
-
- /**
- * Copies a filtered directory to a new location preserving the file dates.
- * <p>
- * This method copies the contents of the specified source directory
- * to within the specified destination directory.
- * <p>
- * The destination directory is created if it does not exist.
- * If the destination directory did exist, then this method merges
- * the source with the destination, with the source taking precedence.
- *
- * <h4>Example: Copy directories only</h4>
- * <pre>
- * // only copy the directory structure
- * FileUtils.copyDirectory(srcDir, destDir, DirectoryFileFilter.DIRECTORY);
- * </pre>
- *
- * <h4>Example: Copy directories and txt files</h4>
- * <pre>
- * // Create a filter for ".txt" files
- * IOFileFilter txtSuffixFilter = FileFilterUtils.suffixFileFilter(".txt");
- * IOFileFilter txtFiles = FileFilterUtils.andFileFilter(FileFileFilter.FILE, txtSuffixFilter);
- *
- * // Create a filter for either directories or ".txt" files
- * FileFilter filter = FileFilterUtils.orFileFilter(DirectoryFileFilter.DIRECTORY, txtFiles);
- *
- * // Copy using the filter
- * FileUtils.copyDirectory(srcDir, destDir, filter);
- * </pre>
- *
- * @param srcDir an existing directory to copy, must not be <code>null</code>
- * @param destDir the new directory, must not be <code>null</code>
- * @param filter the filter to apply, null means copy all directories and files
- * should be the same as the original
- *
- * @throws NullPointerException if source or destination is <code>null</code>
- * @throws IOException if source or destination is invalid
- * @throws IOException if an IO error occurs during copying
- * @since Commons IO 1.4
- */
- public static void copyDirectory(File srcDir, File destDir,
- FileFilter filter) throws IOException {
- copyDirectory(srcDir, destDir, filter, true);
- }
-
- /**
- * Copies a filtered directory to a new location.
- * <p>
- * This method copies the contents of the specified source directory
- * to within the specified destination directory.
- * <p>
- * The destination directory is created if it does not exist.
- * If the destination directory did exist, then this method merges
- * the source with the destination, with the source taking precedence.
- *
- * <h4>Example: Copy directories only</h4>
- * <pre>
- * // only copy the directory structure
- * FileUtils.copyDirectory(srcDir, destDir, DirectoryFileFilter.DIRECTORY, false);
- * </pre>
- *
- * <h4>Example: Copy directories and txt files</h4>
- * <pre>
- * // Create a filter for ".txt" files
- * IOFileFilter txtSuffixFilter = FileFilterUtils.suffixFileFilter(".txt");
- * IOFileFilter txtFiles = FileFilterUtils.andFileFilter(FileFileFilter.FILE, txtSuffixFilter);
- *
- * // Create a filter for either directories or ".txt" files
- * FileFilter filter = FileFilterUtils.orFileFilter(DirectoryFileFilter.DIRECTORY, txtFiles);
- *
- * // Copy using the filter
- * FileUtils.copyDirectory(srcDir, destDir, filter, false);
- * </pre>
- *
- * @param srcDir an existing directory to copy, must not be <code>null</code>
- * @param destDir the new directory, must not be <code>null</code>
- * @param filter the filter to apply, null means copy all directories and files
- * @param preserveFileDate true if the file date of the copy
- * should be the same as the original
- *
- * @throws NullPointerException if source or destination is <code>null</code>
- * @throws IOException if source or destination is invalid
- * @throws IOException if an IO error occurs during copying
- * @since Commons IO 1.4
- */
- public static void copyDirectory(File srcDir, File destDir,
- FileFilter filter, boolean preserveFileDate) throws IOException {
- if (srcDir == null) {
- throw new NullPointerException("Source must not be null");
- }
- if (destDir == null) {
- throw new NullPointerException("Destination must not be null");
- }
- if (srcDir.exists() == false) {
- throw new FileNotFoundException("Source '" + srcDir + "' does not exist");
- }
- if (srcDir.isDirectory() == false) {
- throw new IOException("Source '" + srcDir + "' exists but is not a directory");
- }
- if (srcDir.getCanonicalPath().equals(destDir.getCanonicalPath())) {
- throw new IOException("Source '" + srcDir + "' and destination '" + destDir + "' are the same");
- }
-
- // Cater for destination being directory within the source directory (see IO-141)
- List exclusionList = null;
- if (destDir.getCanonicalPath().startsWith(srcDir.getCanonicalPath())) {
- File[] srcFiles = filter == null ? srcDir.listFiles() : srcDir.listFiles(filter);
- if (srcFiles != null && srcFiles.length > 0) {
- exclusionList = new ArrayList(srcFiles.length);
- for (int i = 0; i < srcFiles.length; i++) {
- File copiedFile = new File(destDir, srcFiles[i].getName());
- exclusionList.add(copiedFile.getCanonicalPath());
- }
- }
- }
- doCopyDirectory(srcDir, destDir, filter, preserveFileDate, exclusionList);
- }
-
- /**
- * Internal copy directory method.
- *
- * @param srcDir the validated source directory, must not be <code>null</code>
- * @param destDir the validated destination directory, must not be <code>null</code>
- * @param filter the filter to apply, null means copy all directories and files
- * @param preserveFileDate whether to preserve the file date
- * @param exclusionList List of files and directories to exclude from the copy, may be null
- * @throws IOException if an error occurs
- * @since Commons IO 1.1
- */
- private static void doCopyDirectory(File srcDir, File destDir, FileFilter filter,
- boolean preserveFileDate, List exclusionList) throws IOException {
- if (destDir.exists()) {
- if (destDir.isDirectory() == false) {
- throw new IOException("Destination '" + destDir + "' exists but is not a directory");
- }
- } else {
- if (destDir.mkdirs() == false) {
- throw new IOException("Destination '" + destDir + "' directory cannot be created");
- }
- if (preserveFileDate) {
- destDir.setLastModified(srcDir.lastModified());
- }
- }
- if (destDir.canWrite() == false) {
- throw new IOException("Destination '" + destDir + "' cannot be written to");
- }
- // recurse
- File[] files = filter == null ? srcDir.listFiles() : srcDir.listFiles(filter);
- if (files == null) { // null if security restricted
- throw new IOException("Failed to list contents of " + srcDir);
- }
- for (int i = 0; i < files.length; i++) {
- File copiedFile = new File(destDir, files[i].getName());
- if (exclusionList == null || !exclusionList.contains(files[i].getCanonicalPath())) {
- if (files[i].isDirectory()) {
- doCopyDirectory(files[i], copiedFile, filter, preserveFileDate, exclusionList);
- } else {
- doCopyFile(files[i], copiedFile, preserveFileDate);
- }
- }
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Copies bytes from the URL <code>source</code> to a file
- * <code>destination</code>. The directories up to <code>destination</code>
- * will be created if they don't already exist. <code>destination</code>
- * will be overwritten if it already exists.
- *
- * @param source the <code>URL</code> to copy bytes from, must not be <code>null</code>
- * @param destination the non-directory <code>File</code> to write bytes to
- * (possibly overwriting), must not be <code>null</code>
- * @throws IOException if <code>source</code> URL cannot be opened
- * @throws IOException if <code>destination</code> is a directory
- * @throws IOException if <code>destination</code> cannot be written
- * @throws IOException if <code>destination</code> needs creating but can't be
- * @throws IOException if an IO error occurs during copying
- */
- public static void copyURLToFile(URL source, File destination) throws IOException {
- InputStream input = source.openStream();
- try {
- FileOutputStream output = openOutputStream(destination);
- try {
- IOUtils.copy(input, output);
- } finally {
- IOUtils.closeQuietly(output);
- }
- } finally {
- IOUtils.closeQuietly(input);
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Deletes a directory recursively.
- *
- * @param directory directory to delete
- * @throws IOException in case deletion is unsuccessful
- */
- public static void deleteDirectory(File directory) throws IOException {
- if (!directory.exists()) {
- return;
- }
-
- cleanDirectory(directory);
- if (!directory.delete()) {
- String message =
- "Unable to delete directory " + directory + ".";
- throw new IOException(message);
- }
- }
-
- /**
- * Deletes a file, never throwing an exception. If file is a directory, delete it and all sub-directories.
- * <p>
- * The difference between File.delete() and this method are:
- * <ul>
- * <li>A directory to be deleted does not have to be empty.</li>
- * <li>No exceptions are thrown when a file or directory cannot be deleted.</li>
- * </ul>
- *
- * @param file file or directory to delete, can be <code>null</code>
- * @return <code>true</code> if the file or directory was deleted, otherwise
- * <code>false</code>
- *
- * @since Commons IO 1.4
- */
- public static boolean deleteQuietly(File file) {
- if (file == null) {
- return false;
- }
- try {
- if (file.isDirectory()) {
- cleanDirectory(file);
- }
- } catch (Exception e) {
- }
-
- try {
- return file.delete();
- } catch (Exception e) {
- return false;
- }
- }
-
- /**
- * Cleans a directory without deleting it.
- *
- * @param directory directory to clean
- * @throws IOException in case cleaning is unsuccessful
- */
- public static void cleanDirectory(File directory) throws IOException {
- if (!directory.exists()) {
- String message = directory + " does not exist";
- throw new IllegalArgumentException(message);
- }
-
- if (!directory.isDirectory()) {
- String message = directory + " is not a directory";
- throw new IllegalArgumentException(message);
- }
-
- File[] files = directory.listFiles();
- if (files == null) { // null if security restricted
- throw new IOException("Failed to list contents of " + directory);
- }
-
- IOException exception = null;
- for (int i = 0; i < files.length; i++) {
- File file = files[i];
- try {
- forceDelete(file);
- } catch (IOException ioe) {
- exception = ioe;
- }
- }
-
- if (null != exception) {
- throw exception;
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Waits for NFS to propagate a file creation, imposing a timeout.
- * <p>
- * This method repeatedly tests {@link File#exists()} until it returns
- * true up to the maximum time specified in seconds.
- *
- * @param file the file to check, must not be <code>null</code>
- * @param seconds the maximum time in seconds to wait
- * @return true if file exists
- * @throws NullPointerException if the file is <code>null</code>
- */
- public static boolean waitFor(File file, int seconds) {
- int timeout = 0;
- int tick = 0;
- while (!file.exists()) {
- if (tick++ >= 10) {
- tick = 0;
- if (timeout++ > seconds) {
- return false;
- }
- }
- try {
- Thread.sleep(100);
- } catch (InterruptedException ignore) {
- // ignore exception
- } catch (Exception ex) {
- break;
- }
- }
- return true;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Reads the contents of a file into a String.
- * The file is always closed.
- *
- * @param file the file to read, must not be <code>null</code>
- * @param encoding the encoding to use, <code>null</code> means platform default
- * @return the file contents, never <code>null</code>
- * @throws IOException in case of an I/O error
- * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
- */
- public static String readFileToString(File file, String encoding) throws IOException {
- InputStream in = null;
- try {
- in = openInputStream(file);
- return IOUtils.toString(in, encoding);
- } finally {
- IOUtils.closeQuietly(in);
- }
- }
-
-
- /**
- * Reads the contents of a file into a String using the default encoding for the VM.
- * The file is always closed.
- *
- * @param file the file to read, must not be <code>null</code>
- * @return the file contents, never <code>null</code>
- * @throws IOException in case of an I/O error
- * @since Commons IO 1.3.1
- */
- public static String readFileToString(File file) throws IOException {
- return readFileToString(file, null);
- }
-
- /**
- * Reads the contents of a file into a byte array.
- * The file is always closed.
- *
- * @param file the file to read, must not be <code>null</code>
- * @return the file contents, never <code>null</code>
- * @throws IOException in case of an I/O error
- * @since Commons IO 1.1
- */
- public static byte[] readFileToByteArray(File file) throws IOException {
- InputStream in = null;
- try {
- in = openInputStream(file);
- return IOUtils.toByteArray(in);
- } finally {
- IOUtils.closeQuietly(in);
- }
- }
-
- /**
- * Reads the contents of a file line by line to a List of Strings.
- * The file is always closed.
- *
- * @param file the file to read, must not be <code>null</code>
- * @param encoding the encoding to use, <code>null</code> means platform default
- * @return the list of Strings representing each line in the file, never <code>null</code>
- * @throws IOException in case of an I/O error
- * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
- * @since Commons IO 1.1
- */
- public static List readLines(File file, String encoding) throws IOException {
- InputStream in = null;
- try {
- in = openInputStream(file);
- return IOUtils.readLines(in, encoding);
- } finally {
- IOUtils.closeQuietly(in);
- }
- }
-
- /**
- * Reads the contents of a file line by line to a List of Strings using the default encoding for the VM.
- * The file is always closed.
- *
- * @param file the file to read, must not be <code>null</code>
- * @return the list of Strings representing each line in the file, never <code>null</code>
- * @throws IOException in case of an I/O error
- * @since Commons IO 1.3
- */
- public static List readLines(File file) throws IOException {
- return readLines(file, null);
- }
-
- /**
- * Returns an Iterator for the lines in a <code>File</code>.
- * <p>
- * This method opens an <code>InputStream</code> for the file.
- * When you have finished with the iterator you should close the stream
- * to free internal resources. This can be done by calling the
- * {@link LineIterator#close()} or
- * {@link LineIterator#closeQuietly(LineIterator)} method.
- * <p>
- * The recommended usage pattern is:
- * <pre>
- * LineIterator it = FileUtils.lineIterator(file, "UTF-8");
- * try {
- * while (it.hasNext()) {
- * String line = it.nextLine();
- * /// do something with line
- * }
- * } finally {
- * LineIterator.closeQuietly(iterator);
- * }
- * </pre>
- * <p>
- * If an exception occurs during the creation of the iterator, the
- * underlying stream is closed.
- *
- * @param file the file to open for input, must not be <code>null</code>
- * @param encoding the encoding to use, <code>null</code> means platform default
- * @return an Iterator of the lines in the file, never <code>null</code>
- * @throws IOException in case of an I/O error (file closed)
- * @since Commons IO 1.2
- */
- public static LineIterator lineIterator(File file, String encoding) throws IOException {
- InputStream in = null;
- try {
- in = openInputStream(file);
- return IOUtils.lineIterator(in, encoding);
- } catch (IOException ex) {
- IOUtils.closeQuietly(in);
- throw ex;
- } catch (RuntimeException ex) {
- IOUtils.closeQuietly(in);
- throw ex;
- }
- }
-
- /**
- * Returns an Iterator for the lines in a <code>File</code> using the default encoding for the VM.
- *
- * @param file the file to open for input, must not be <code>null</code>
- * @return an Iterator of the lines in the file, never <code>null</code>
- * @throws IOException in case of an I/O error (file closed)
- * @since Commons IO 1.3
- * @see #lineIterator(File, String)
- */
- public static LineIterator lineIterator(File file) throws IOException {
- return lineIterator(file, null);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Writes a String to a file creating the file if it does not exist.
- *
- * NOTE: As from v1.3, the parent directories of the file will be created
- * if they do not exist.
- *
- * @param file the file to write
- * @param data the content to write to the file
- * @param encoding the encoding to use, <code>null</code> means platform default
- * @throws IOException in case of an I/O error
- * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
- */
- public static void writeStringToFile(File file, String data, String encoding) throws IOException {
- OutputStream out = null;
- try {
- out = openOutputStream(file);
- IOUtils.write(data, out, encoding);
- } finally {
- IOUtils.closeQuietly(out);
- }
- }
-
- /**
- * Writes a String to a file creating the file if it does not exist using the default encoding for the VM.
- *
- * @param file the file to write
- * @param data the content to write to the file
- * @throws IOException in case of an I/O error
- */
- public static void writeStringToFile(File file, String data) throws IOException {
- writeStringToFile(file, data, null);
- }
-
- /**
- * Writes a byte array to a file creating the file if it does not exist.
- * <p>
- * NOTE: As from v1.3, the parent directories of the file will be created
- * if they do not exist.
- *
- * @param file the file to write to
- * @param data the content to write to the file
- * @throws IOException in case of an I/O error
- * @since Commons IO 1.1
- */
- public static void writeByteArrayToFile(File file, byte[] data) throws IOException {
- OutputStream out = null;
- try {
- out = openOutputStream(file);
- out.write(data);
- } finally {
- IOUtils.closeQuietly(out);
- }
- }
-
- /**
- * Writes the <code>toString()</code> value of each item in a collection to
- * the specified <code>File</code> line by line.
- * The specified character encoding and the default line ending will be used.
- * <p>
- * NOTE: As from v1.3, the parent directories of the file will be created
- * if they do not exist.
- *
- * @param file the file to write to
- * @param encoding the encoding to use, <code>null</code> means platform default
- * @param lines the lines to write, <code>null</code> entries produce blank lines
- * @throws IOException in case of an I/O error
- * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
- * @since Commons IO 1.1
- */
- public static void writeLines(File file, String encoding, Collection lines) throws IOException {
- writeLines(file, encoding, lines, null);
- }
-
- /**
- * Writes the <code>toString()</code> value of each item in a collection to
- * the specified <code>File</code> line by line.
- * The default VM encoding and the default line ending will be used.
- *
- * @param file the file to write to
- * @param lines the lines to write, <code>null</code> entries produce blank lines
- * @throws IOException in case of an I/O error
- * @since Commons IO 1.3
- */
- public static void writeLines(File file, Collection lines) throws IOException {
- writeLines(file, null, lines, null);
- }
-
- /**
- * Writes the <code>toString()</code> value of each item in a collection to
- * the specified <code>File</code> line by line.
- * The specified character encoding and the line ending will be used.
- * <p>
- * NOTE: As from v1.3, the parent directories of the file will be created
- * if they do not exist.
- *
- * @param file the file to write to
- * @param encoding the encoding to use, <code>null</code> means platform default
- * @param lines the lines to write, <code>null</code> entries produce blank lines
- * @param lineEnding the line separator to use, <code>null</code> is system default
- * @throws IOException in case of an I/O error
- * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
- * @since Commons IO 1.1
- */
- public static void writeLines(File file, String encoding, Collection lines, String lineEnding) throws IOException {
- OutputStream out = null;
- try {
- out = openOutputStream(file);
- IOUtils.writeLines(lines, lineEnding, out, encoding);
- } finally {
- IOUtils.closeQuietly(out);
- }
- }
-
- /**
- * Writes the <code>toString()</code> value of each item in a collection to
- * the specified <code>File</code> line by line.
- * The default VM encoding and the specified line ending will be used.
- *
- * @param file the file to write to
- * @param lines the lines to write, <code>null</code> entries produce blank lines
- * @param lineEnding the line separator to use, <code>null</code> is system default
- * @throws IOException in case of an I/O error
- * @since Commons IO 1.3
- */
- public static void writeLines(File file, Collection lines, String lineEnding) throws IOException {
- writeLines(file, null, lines, lineEnding);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Deletes a file. If file is a directory, delete it and all sub-directories.
- * <p>
- * The difference between File.delete() and this method are:
- * <ul>
- * <li>A directory to be deleted does not have to be empty.</li>
- * <li>You get exceptions when a file or directory cannot be deleted.
- * (java.io.File methods returns a boolean)</li>
- * </ul>
- *
- * @param file file or directory to delete, must not be <code>null</code>
- * @throws NullPointerException if the directory is <code>null</code>
- * @throws FileNotFoundException if the file was not found
- * @throws IOException in case deletion is unsuccessful
- */
- public static void forceDelete(File file) throws IOException {
- if (file.isDirectory()) {
- deleteDirectory(file);
- } else {
- boolean filePresent = file.exists();
- if (!file.delete()) {
- if (!filePresent){
- throw new FileNotFoundException("File does not exist: " + file);
- }
- String message =
- "Unable to delete file: " + file;
- throw new IOException(message);
- }
- }
- }
-
- /**
- * Schedules a file to be deleted when JVM exits.
- * If file is directory delete it and all sub-directories.
- *
- * @param file file or directory to delete, must not be <code>null</code>
- * @throws NullPointerException if the file is <code>null</code>
- * @throws IOException in case deletion is unsuccessful
- */
- public static void forceDeleteOnExit(File file) throws IOException {
- if (file.isDirectory()) {
- deleteDirectoryOnExit(file);
- } else {
- file.deleteOnExit();
- }
- }
-
- /**
- * Schedules a directory recursively for deletion on JVM exit.
- *
- * @param directory directory to delete, must not be <code>null</code>
- * @throws NullPointerException if the directory is <code>null</code>
- * @throws IOException in case deletion is unsuccessful
- */
- private static void deleteDirectoryOnExit(File directory) throws IOException {
- if (!directory.exists()) {
- return;
- }
-
- cleanDirectoryOnExit(directory);
- directory.deleteOnExit();
- }
-
- /**
- * Cleans a directory without deleting it.
- *
- * @param directory directory to clean, must not be <code>null</code>
- * @throws NullPointerException if the directory is <code>null</code>
- * @throws IOException in case cleaning is unsuccessful
- */
- private static void cleanDirectoryOnExit(File directory) throws IOException {
- if (!directory.exists()) {
- String message = directory + " does not exist";
- throw new IllegalArgumentException(message);
- }
-
- if (!directory.isDirectory()) {
- String message = directory + " is not a directory";
- throw new IllegalArgumentException(message);
- }
-
- File[] files = directory.listFiles();
- if (files == null) { // null if security restricted
- throw new IOException("Failed to list contents of " + directory);
- }
-
- IOException exception = null;
- for (int i = 0; i < files.length; i++) {
- File file = files[i];
- try {
- forceDeleteOnExit(file);
- } catch (IOException ioe) {
- exception = ioe;
- }
- }
-
- if (null != exception) {
- throw exception;
- }
- }
-
- /**
- * Makes a directory, including any necessary but nonexistent parent
- * directories. If there already exists a file with specified name or
- * the directory cannot be created then an exception is thrown.
- *
- * @param directory directory to create, must not be <code>null</code>
- * @throws NullPointerException if the directory is <code>null</code>
- * @throws IOException if the directory cannot be created
- */
- public static void forceMkdir(File directory) throws IOException {
- if (directory.exists()) {
- if (directory.isFile()) {
- String message =
- "File "
- + directory
- + " exists and is "
- + "not a directory. Unable to create directory.";
- throw new IOException(message);
- }
- } else {
- if (!directory.mkdirs()) {
- String message =
- "Unable to create directory " + directory;
- throw new IOException(message);
- }
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Counts the size of a directory recursively (sum of the length of all files).
- *
- * @param directory directory to inspect, must not be <code>null</code>
- * @return size of directory in bytes, 0 if directory is security restricted
- * @throws NullPointerException if the directory is <code>null</code>
- */
- public static long sizeOfDirectory(File directory) {
- if (!directory.exists()) {
- String message = directory + " does not exist";
- throw new IllegalArgumentException(message);
- }
-
- if (!directory.isDirectory()) {
- String message = directory + " is not a directory";
- throw new IllegalArgumentException(message);
- }
-
- long size = 0;
-
- File[] files = directory.listFiles();
- if (files == null) { // null if security restricted
- return 0L;
- }
- for (int i = 0; i < files.length; i++) {
- File file = files[i];
-
- if (file.isDirectory()) {
- size += sizeOfDirectory(file);
- } else {
- size += file.length();
- }
- }
-
- return size;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Tests if the specified <code>File</code> is newer than the reference
- * <code>File</code>.
- *
- * @param file the <code>File</code> of which the modification date must
- * be compared, must not be <code>null</code>
- * @param reference the <code>File</code> of which the modification date
- * is used, must not be <code>null</code>
- * @return true if the <code>File</code> exists and has been modified more
- * recently than the reference <code>File</code>
- * @throws IllegalArgumentException if the file is <code>null</code>
- * @throws IllegalArgumentException if the reference file is <code>null</code> or doesn't exist
- */
- public static boolean isFileNewer(File file, File reference) {
- if (reference == null) {
- throw new IllegalArgumentException("No specified reference file");
- }
- if (!reference.exists()) {
- throw new IllegalArgumentException("The reference file '"
- + file + "' doesn't exist");
- }
- return isFileNewer(file, reference.lastModified());
- }
-
- /**
- * Tests if the specified <code>File</code> is newer than the specified
- * <code>Date</code>.
- *
- * @param file the <code>File</code> of which the modification date
- * must be compared, must not be <code>null</code>
- * @param date the date reference, must not be <code>null</code>
- * @return true if the <code>File</code> exists and has been modified
- * after the given <code>Date</code>.
- * @throws IllegalArgumentException if the file is <code>null</code>
- * @throws IllegalArgumentException if the date is <code>null</code>
- */
- public static boolean isFileNewer(File file, Date date) {
- if (date == null) {
- throw new IllegalArgumentException("No specified date");
- }
- return isFileNewer(file, date.getTime());
- }
-
- /**
- * Tests if the specified <code>File</code> is newer than the specified
- * time reference.
- *
- * @param file the <code>File</code> of which the modification date must
- * be compared, must not be <code>null</code>
- * @param timeMillis the time reference measured in milliseconds since the
- * epoch (00:00:00 GMT, January 1, 1970)
- * @return true if the <code>File</code> exists and has been modified after
- * the given time reference.
- * @throws IllegalArgumentException if the file is <code>null</code>
- */
- public static boolean isFileNewer(File file, long timeMillis) {
- if (file == null) {
- throw new IllegalArgumentException("No specified file");
- }
- if (!file.exists()) {
- return false;
- }
- return file.lastModified() > timeMillis;
- }
-
-
- //-----------------------------------------------------------------------
- /**
- * Tests if the specified <code>File</code> is older than the reference
- * <code>File</code>.
- *
- * @param file the <code>File</code> of which the modification date must
- * be compared, must not be <code>null</code>
- * @param reference the <code>File</code> of which the modification date
- * is used, must not be <code>null</code>
- * @return true if the <code>File</code> exists and has been modified before
- * the reference <code>File</code>
- * @throws IllegalArgumentException if the file is <code>null</code>
- * @throws IllegalArgumentException if the reference file is <code>null</code> or doesn't exist
- */
- public static boolean isFileOlder(File file, File reference) {
- if (reference == null) {
- throw new IllegalArgumentException("No specified reference file");
- }
- if (!reference.exists()) {
- throw new IllegalArgumentException("The reference file '"
- + file + "' doesn't exist");
- }
- return isFileOlder(file, reference.lastModified());
- }
-
- /**
- * Tests if the specified <code>File</code> is older than the specified
- * <code>Date</code>.
- *
- * @param file the <code>File</code> of which the modification date
- * must be compared, must not be <code>null</code>
- * @param date the date reference, must not be <code>null</code>
- * @return true if the <code>File</code> exists and has been modified
- * before the given <code>Date</code>.
- * @throws IllegalArgumentException if the file is <code>null</code>
- * @throws IllegalArgumentException if the date is <code>null</code>
- */
- public static boolean isFileOlder(File file, Date date) {
- if (date == null) {
- throw new IllegalArgumentException("No specified date");
- }
- return isFileOlder(file, date.getTime());
- }
-
- /**
- * Tests if the specified <code>File</code> is older than the specified
- * time reference.
- *
- * @param file the <code>File</code> of which the modification date must
- * be compared, must not be <code>null</code>
- * @param timeMillis the time reference measured in milliseconds since the
- * epoch (00:00:00 GMT, January 1, 1970)
- * @return true if the <code>File</code> exists and has been modified before
- * the given time reference.
- * @throws IllegalArgumentException if the file is <code>null</code>
- */
- public static boolean isFileOlder(File file, long timeMillis) {
- if (file == null) {
- throw new IllegalArgumentException("No specified file");
- }
- if (!file.exists()) {
- return false;
- }
- return file.lastModified() < timeMillis;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Computes the checksum of a file using the CRC32 checksum routine.
- * The value of the checksum is returned.
- *
- * @param file the file to checksum, must not be <code>null</code>
- * @return the checksum value
- * @throws NullPointerException if the file or checksum is <code>null</code>
- * @throws IllegalArgumentException if the file is a directory
- * @throws IOException if an IO error occurs reading the file
- * @since Commons IO 1.3
- */
- public static long checksumCRC32(File file) throws IOException {
- CRC32 crc = new CRC32();
- checksum(file, crc);
- return crc.getValue();
- }
-
- /**
- * Computes the checksum of a file using the specified checksum object.
- * Multiple files may be checked using one <code>Checksum</code> instance
- * if desired simply by reusing the same checksum object.
- * For example:
- * <pre>
- * long csum = FileUtils.checksum(file, new CRC32()).getValue();
- * </pre>
- *
- * @param file the file to checksum, must not be <code>null</code>
- * @param checksum the checksum object to be used, must not be <code>null</code>
- * @return the checksum specified, updated with the content of the file
- * @throws NullPointerException if the file or checksum is <code>null</code>
- * @throws IllegalArgumentException if the file is a directory
- * @throws IOException if an IO error occurs reading the file
- * @since Commons IO 1.3
- */
- public static Checksum checksum(File file, Checksum checksum) throws IOException {
- if (file.isDirectory()) {
- throw new IllegalArgumentException("Checksums can't be computed on directories");
- }
- InputStream in = null;
- try {
- in = new CheckedInputStream(new FileInputStream(file), checksum);
- IOUtils.copy(in, new NullOutputStream());
- } finally {
- IOUtils.closeQuietly(in);
- }
- return checksum;
- }
-
- /**
- * Moves a directory.
- * <p>
- * When the destination directory is on another file system, do a "copy and delete".
- *
- * @param srcDir the directory to be moved
- * @param destDir the destination directory
- * @throws NullPointerException if source or destination is <code>null</code>
- * @throws IOException if source or destination is invalid
- * @throws IOException if an IO error occurs moving the file
- * @since Commons IO 1.4
- */
- public static void moveDirectory(File srcDir, File destDir) throws IOException {
- if (srcDir == null) {
- throw new NullPointerException("Source must not be null");
- }
- if (destDir == null) {
- throw new NullPointerException("Destination must not be null");
- }
- if (!srcDir.exists()) {
- throw new FileNotFoundException("Source '" + srcDir + "' does not exist");
- }
- if (!srcDir.isDirectory()) {
- throw new IOException("Source '" + srcDir + "' is not a directory");
- }
- if (destDir.exists()) {
- throw new IOException("Destination '" + destDir + "' already exists");
- }
- boolean rename = srcDir.renameTo(destDir);
- if (!rename) {
- copyDirectory( srcDir, destDir );
- deleteDirectory( srcDir );
- if (srcDir.exists()) {
- throw new IOException("Failed to delete original directory '" + srcDir +
- "' after copy to '" + destDir + "'");
- }
- }
- }
-
- /**
- * Moves a directory to another directory.
- *
- * @param src the file to be moved
- * @param destDir the destination file
- * @param createDestDir If <code>true</code> create the destination directory,
- * otherwise if <code>false</code> throw an IOException
- * @throws NullPointerException if source or destination is <code>null</code>
- * @throws IOException if source or destination is invalid
- * @throws IOException if an IO error occurs moving the file
- * @since Commons IO 1.4
- */
- public static void moveDirectoryToDirectory(File src, File destDir, boolean createDestDir) throws IOException {
- if (src == null) {
- throw new NullPointerException("Source must not be null");
- }
- if (destDir == null) {
- throw new NullPointerException("Destination directory must not be null");
- }
- if (!destDir.exists() && createDestDir) {
- destDir.mkdirs();
- }
- if (!destDir.exists()) {
- throw new FileNotFoundException("Destination directory '" + destDir +
- "' does not exist [createDestDir=" + createDestDir +"]");
- }
- if (!destDir.isDirectory()) {
- throw new IOException("Destination '" + destDir + "' is not a directory");
- }
- moveDirectory(src, new File(destDir, src.getName()));
-
- }
-
- /**
- * Moves a file.
- * <p>
- * When the destination file is on another file system, do a "copy and delete".
- *
- * @param srcFile the file to be moved
- * @param destFile the destination file
- * @throws NullPointerException if source or destination is <code>null</code>
- * @throws IOException if source or destination is invalid
- * @throws IOException if an IO error occurs moving the file
- * @since Commons IO 1.4
- */
- public static void moveFile(File srcFile, File destFile) throws IOException {
- if (srcFile == null) {
- throw new NullPointerException("Source must not be null");
- }
- if (destFile == null) {
- throw new NullPointerException("Destination must not be null");
- }
- if (!srcFile.exists()) {
- throw new FileNotFoundException("Source '" + srcFile + "' does not exist");
- }
- if (srcFile.isDirectory()) {
- throw new IOException("Source '" + srcFile + "' is a directory");
- }
- if (destFile.exists()) {
- throw new IOException("Destination '" + destFile + "' already exists");
- }
- if (destFile.isDirectory()) {
- throw new IOException("Destination '" + destFile + "' is a directory");
- }
- boolean rename = srcFile.renameTo(destFile);
- if (!rename) {
- copyFile( srcFile, destFile );
- if (!srcFile.delete()) {
- FileUtils.deleteQuietly(destFile);
- throw new IOException("Failed to delete original file '" + srcFile +
- "' after copy to '" + destFile + "'");
- }
- }
- }
-
- /**
- * Moves a file to a directory.
- *
- * @param srcFile the file to be moved
- * @param destDir the destination file
- * @param createDestDir If <code>true</code> create the destination directory,
- * otherwise if <code>false</code> throw an IOException
- * @throws NullPointerException if source or destination is <code>null</code>
- * @throws IOException if source or destination is invalid
- * @throws IOException if an IO error occurs moving the file
- * @since Commons IO 1.4
- */
- public static void moveFileToDirectory(File srcFile, File destDir, boolean createDestDir) throws IOException {
- if (srcFile == null) {
- throw new NullPointerException("Source must not be null");
- }
- if (destDir == null) {
- throw new NullPointerException("Destination directory must not be null");
- }
- if (!destDir.exists() && createDestDir) {
- destDir.mkdirs();
- }
- if (!destDir.exists()) {
- throw new FileNotFoundException("Destination directory '" + destDir +
- "' does not exist [createDestDir=" + createDestDir +"]");
- }
- if (!destDir.isDirectory()) {
- throw new IOException("Destination '" + destDir + "' is not a directory");
- }
- moveFile(srcFile, new File(destDir, srcFile.getName()));
- }
-
- /**
- * Moves a file or directory to the destination directory.
- * <p>
- * When the destination is on another file system, do a "copy and delete".
- *
- * @param src the file or directory to be moved
- * @param destDir the destination directory
- * @param createDestDir If <code>true</code> create the destination directory,
- * otherwise if <code>false</code> throw an IOException
- * @throws NullPointerException if source or destination is <code>null</code>
- * @throws IOException if source or destination is invalid
- * @throws IOException if an IO error occurs moving the file
- * @since Commons IO 1.4
- */
- public static void moveToDirectory(File src, File destDir, boolean createDestDir) throws IOException {
- if (src == null) {
- throw new NullPointerException("Source must not be null");
- }
- if (destDir == null) {
- throw new NullPointerException("Destination must not be null");
- }
- if (!src.exists()) {
- throw new FileNotFoundException("Source '" + src + "' does not exist");
- }
- if (src.isDirectory()) {
- moveDirectoryToDirectory(src, destDir, createDestDir);
- } else {
- moveFileToDirectory(src, destDir, createDestDir);
- }
- }
-
-}
diff --git a/src/org/apache/commons/io/FilenameUtils.java b/src/org/apache/commons/io/FilenameUtils.java
deleted file mode 100644
index 8e170b147..000000000
--- a/src/org/apache/commons/io/FilenameUtils.java
+++ /dev/null
@@ -1,1260 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Stack;
-
-/**
- * General filename and filepath manipulation utilities.
- * <p>
- * When dealing with filenames you can hit problems when moving from a Windows
- * based development machine to a Unix based production machine.
- * This class aims to help avoid those problems.
- * <p>
- * <b>NOTE</b>: You may be able to avoid using this class entirely simply by
- * using JDK {@link java.io.File File} objects and the two argument constructor
- * {@link java.io.File#File(java.io.File, java.lang.String) File(File,String)}.
- * <p>
- * Most methods on this class are designed to work the same on both Unix and Windows.
- * Those that don't include 'System', 'Unix' or 'Windows' in their name.
- * <p>
- * Most methods recognise both separators (forward and back), and both
- * sets of prefixes. See the javadoc of each method for details.
- * <p>
- * This class defines six components within a filename
- * (example C:\dev\project\file.txt):
- * <ul>
- * <li>the prefix - C:\</li>
- * <li>the path - dev\project\</li>
- * <li>the full path - C:\dev\project\</li>
- * <li>the name - file.txt</li>
- * <li>the base name - file</li>
- * <li>the extension - txt</li>
- * </ul>
- * Note that this class works best if directory filenames end with a separator.
- * If you omit the last separator, it is impossible to determine if the filename
- * corresponds to a file or a directory. As a result, we have chosen to say
- * it corresponds to a file.
- * <p>
- * This class only supports Unix and Windows style names.
- * Prefixes are matched as follows:
- * <pre>
- * Windows:
- * a\b\c.txt --> "" --> relative
- * \a\b\c.txt --> "\" --> current drive absolute
- * C:a\b\c.txt --> "C:" --> drive relative
- * C:\a\b\c.txt --> "C:\" --> absolute
- * \\server\a\b\c.txt --> "\\server\" --> UNC
- *
- * Unix:
- * a/b/c.txt --> "" --> relative
- * /a/b/c.txt --> "/" --> absolute
- * ~/a/b/c.txt --> "~/" --> current user
- * ~ --> "~/" --> current user (slash added)
- * ~user/a/b/c.txt --> "~user/" --> named user
- * ~user --> "~user/" --> named user (slash added)
- * </pre>
- * Both prefix styles are matched always, irrespective of the machine that you are
- * currently running on.
- * <p>
- * Origin of code: Excalibur, Alexandria, Tomcat, Commons-Utils.
- *
- * @author <a href="mailto:burton@relativity.yi.org">Kevin A. Burton</A>
- * @author <a href="mailto:sanders@apache.org">Scott Sanders</a>
- * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
- * @author <a href="mailto:Christoph.Reck@dlr.de">Christoph.Reck</a>
- * @author <a href="mailto:peter@apache.org">Peter Donald</a>
- * @author <a href="mailto:jefft@apache.org">Jeff Turner</a>
- * @author Matthew Hawthorne
- * @author Martin Cooper
- * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
- * @author Stephen Colebourne
- * @version $Id: FilenameUtils.java 609870 2008-01-08 04:46:26Z niallp $
- * @since Commons IO 1.1
- */
-public class FilenameUtils {
-
- /**
- * The extension separator character.
- * @since Commons IO 1.4
- */
- public static final char EXTENSION_SEPARATOR = '.';
-
- /**
- * The extension separator String.
- * @since Commons IO 1.4
- */
- public static final String EXTENSION_SEPARATOR_STR = (new Character(EXTENSION_SEPARATOR)).toString();
-
- /**
- * The Unix separator character.
- */
- private static final char UNIX_SEPARATOR = '/';
-
- /**
- * The Windows separator character.
- */
- private static final char WINDOWS_SEPARATOR = '\\';
-
- /**
- * The system separator character.
- */
- private static final char SYSTEM_SEPARATOR = File.separatorChar;
-
- /**
- * The separator character that is the opposite of the system separator.
- */
- private static final char OTHER_SEPARATOR;
- static {
- if (isSystemWindows()) {
- OTHER_SEPARATOR = UNIX_SEPARATOR;
- } else {
- OTHER_SEPARATOR = WINDOWS_SEPARATOR;
- }
- }
-
- /**
- * Instances should NOT be constructed in standard programming.
- */
- public FilenameUtils() {
- super();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Determines if Windows file system is in use.
- *
- * @return true if the system is Windows
- */
- static boolean isSystemWindows() {
- return SYSTEM_SEPARATOR == WINDOWS_SEPARATOR;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Checks if the character is a separator.
- *
- * @param ch the character to check
- * @return true if it is a separator character
- */
- private static boolean isSeparator(char ch) {
- return (ch == UNIX_SEPARATOR) || (ch == WINDOWS_SEPARATOR);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Normalizes a path, removing double and single dot path steps.
- * <p>
- * This method normalizes a path to a standard format.
- * The input may contain separators in either Unix or Windows format.
- * The output will contain separators in the format of the system.
- * <p>
- * A trailing slash will be retained.
- * A double slash will be merged to a single slash (but UNC names are handled).
- * A single dot path segment will be removed.
- * A double dot will cause that path segment and the one before to be removed.
- * If the double dot has no parent path segment to work with, <code>null</code>
- * is returned.
- * <p>
- * The output will be the same on both Unix and Windows except
- * for the separator character.
- * <pre>
- * /foo// --> /foo/
- * /foo/./ --> /foo/
- * /foo/../bar --> /bar
- * /foo/../bar/ --> /bar/
- * /foo/../bar/../baz --> /baz
- * //foo//./bar --> /foo/bar
- * /../ --> null
- * ../foo --> null
- * foo/bar/.. --> foo/
- * foo/../../bar --> null
- * foo/../bar --> bar
- * //server/foo/../bar --> //server/bar
- * //server/../bar --> null
- * C:\foo\..\bar --> C:\bar
- * C:\..\bar --> null
- * ~/foo/../bar/ --> ~/bar/
- * ~/../bar --> null
- * </pre>
- * (Note the file separator returned will be correct for Windows/Unix)
- *
- * @param filename the filename to normalize, null returns null
- * @return the normalized filename, or null if invalid
- */
- public static String normalize(String filename) {
- return doNormalize(filename, true);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Normalizes a path, removing double and single dot path steps,
- * and removing any final directory separator.
- * <p>
- * This method normalizes a path to a standard format.
- * The input may contain separators in either Unix or Windows format.
- * The output will contain separators in the format of the system.
- * <p>
- * A trailing slash will be removed.
- * A double slash will be merged to a single slash (but UNC names are handled).
- * A single dot path segment will be removed.
- * A double dot will cause that path segment and the one before to be removed.
- * If the double dot has no parent path segment to work with, <code>null</code>
- * is returned.
- * <p>
- * The output will be the same on both Unix and Windows except
- * for the separator character.
- * <pre>
- * /foo// --> /foo
- * /foo/./ --> /foo
- * /foo/../bar --> /bar
- * /foo/../bar/ --> /bar
- * /foo/../bar/../baz --> /baz
- * //foo//./bar --> /foo/bar
- * /../ --> null
- * ../foo --> null
- * foo/bar/.. --> foo
- * foo/../../bar --> null
- * foo/../bar --> bar
- * //server/foo/../bar --> //server/bar
- * //server/../bar --> null
- * C:\foo\..\bar --> C:\bar
- * C:\..\bar --> null
- * ~/foo/../bar/ --> ~/bar
- * ~/../bar --> null
- * </pre>
- * (Note the file separator returned will be correct for Windows/Unix)
- *
- * @param filename the filename to normalize, null returns null
- * @return the normalized filename, or null if invalid
- */
- public static String normalizeNoEndSeparator(String filename) {
- return doNormalize(filename, false);
- }
-
- /**
- * Internal method to perform the normalization.
- *
- * @param filename the filename
- * @param keepSeparator true to keep the final separator
- * @return the normalized filename
- */
- private static String doNormalize(String filename, boolean keepSeparator) {
- if (filename == null) {
- return null;
- }
- int size = filename.length();
- if (size == 0) {
- return filename;
- }
- int prefix = getPrefixLength(filename);
- if (prefix < 0) {
- return null;
- }
-
- char[] array = new char[size + 2]; // +1 for possible extra slash, +2 for arraycopy
- filename.getChars(0, filename.length(), array, 0);
-
- // fix separators throughout
- for (int i = 0; i < array.length; i++) {
- if (array[i] == OTHER_SEPARATOR) {
- array[i] = SYSTEM_SEPARATOR;
- }
- }
-
- // add extra separator on the end to simplify code below
- boolean lastIsDirectory = true;
- if (array[size - 1] != SYSTEM_SEPARATOR) {
- array[size++] = SYSTEM_SEPARATOR;
- lastIsDirectory = false;
- }
-
- // adjoining slashes
- for (int i = prefix + 1; i < size; i++) {
- if (array[i] == SYSTEM_SEPARATOR && array[i - 1] == SYSTEM_SEPARATOR) {
- System.arraycopy(array, i, array, i - 1, size - i);
- size--;
- i--;
- }
- }
-
- // dot slash
- for (int i = prefix + 1; i < size; i++) {
- if (array[i] == SYSTEM_SEPARATOR && array[i - 1] == '.' &&
- (i == prefix + 1 || array[i - 2] == SYSTEM_SEPARATOR)) {
- if (i == size - 1) {
- lastIsDirectory = true;
- }
- System.arraycopy(array, i + 1, array, i - 1, size - i);
- size -=2;
- i--;
- }
- }
-
- // double dot slash
- outer:
- for (int i = prefix + 2; i < size; i++) {
- if (array[i] == SYSTEM_SEPARATOR && array[i - 1] == '.' && array[i - 2] == '.' &&
- (i == prefix + 2 || array[i - 3] == SYSTEM_SEPARATOR)) {
- if (i == prefix + 2) {
- return null;
- }
- if (i == size - 1) {
- lastIsDirectory = true;
- }
- int j;
- for (j = i - 4 ; j >= prefix; j--) {
- if (array[j] == SYSTEM_SEPARATOR) {
- // remove b/../ from a/b/../c
- System.arraycopy(array, i + 1, array, j + 1, size - i);
- size -= (i - j);
- i = j + 1;
- continue outer;
- }
- }
- // remove a/../ from a/../c
- System.arraycopy(array, i + 1, array, prefix, size - i);
- size -= (i + 1 - prefix);
- i = prefix + 1;
- }
- }
-
- if (size <= 0) { // should never be less than 0
- return "";
- }
- if (size <= prefix) { // should never be less than prefix
- return new String(array, 0, size);
- }
- if (lastIsDirectory && keepSeparator) {
- return new String(array, 0, size); // keep trailing separator
- }
- return new String(array, 0, size - 1); // lose trailing separator
- }
-
- //-----------------------------------------------------------------------
- /**
- * Concatenates a filename to a base path using normal command line style rules.
- * <p>
- * The effect is equivalent to resultant directory after changing
- * directory to the first argument, followed by changing directory to
- * the second argument.
- * <p>
- * The first argument is the base path, the second is the path to concatenate.
- * The returned path is always normalized via {@link #normalize(String)},
- * thus <code>..</code> is handled.
- * <p>
- * If <code>pathToAdd</code> is absolute (has an absolute prefix), then
- * it will be normalized and returned.
- * Otherwise, the paths will be joined, normalized and returned.
- * <p>
- * The output will be the same on both Unix and Windows except
- * for the separator character.
- * <pre>
- * /foo/ + bar --> /foo/bar
- * /foo + bar --> /foo/bar
- * /foo + /bar --> /bar
- * /foo + C:/bar --> C:/bar
- * /foo + C:bar --> C:bar (*)
- * /foo/a/ + ../bar --> foo/bar
- * /foo/ + ../../bar --> null
- * /foo/ + /bar --> /bar
- * /foo/.. + /bar --> /bar
- * /foo + bar/c.txt --> /foo/bar/c.txt
- * /foo/c.txt + bar --> /foo/c.txt/bar (!)
- * </pre>
- * (*) Note that the Windows relative drive prefix is unreliable when
- * used with this method.
- * (!) Note that the first parameter must be a path. If it ends with a name, then
- * the name will be built into the concatenated path. If this might be a problem,
- * use {@link #getFullPath(String)} on the base path argument.
- *
- * @param basePath the base path to attach to, always treated as a path
- * @param fullFilenameToAdd the filename (or path) to attach to the base
- * @return the concatenated path, or null if invalid
- */
- public static String concat(String basePath, String fullFilenameToAdd) {
- int prefix = getPrefixLength(fullFilenameToAdd);
- if (prefix < 0) {
- return null;
- }
- if (prefix > 0) {
- return normalize(fullFilenameToAdd);
- }
- if (basePath == null) {
- return null;
- }
- int len = basePath.length();
- if (len == 0) {
- return normalize(fullFilenameToAdd);
- }
- char ch = basePath.charAt(len - 1);
- if (isSeparator(ch)) {
- return normalize(basePath + fullFilenameToAdd);
- } else {
- return normalize(basePath + '/' + fullFilenameToAdd);
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Converts all separators to the Unix separator of forward slash.
- *
- * @param path the path to be changed, null ignored
- * @return the updated path
- */
- public static String separatorsToUnix(String path) {
- if (path == null || path.indexOf(WINDOWS_SEPARATOR) == -1) {
- return path;
- }
- return path.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR);
- }
-
- /**
- * Converts all separators to the Windows separator of backslash.
- *
- * @param path the path to be changed, null ignored
- * @return the updated path
- */
- public static String separatorsToWindows(String path) {
- if (path == null || path.indexOf(UNIX_SEPARATOR) == -1) {
- return path;
- }
- return path.replace(UNIX_SEPARATOR, WINDOWS_SEPARATOR);
- }
-
- /**
- * Converts all separators to the system separator.
- *
- * @param path the path to be changed, null ignored
- * @return the updated path
- */
- public static String separatorsToSystem(String path) {
- if (path == null) {
- return null;
- }
- if (isSystemWindows()) {
- return separatorsToWindows(path);
- } else {
- return separatorsToUnix(path);
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Returns the length of the filename prefix, such as <code>C:/</code> or <code>~/</code>.
- * <p>
- * This method will handle a file in either Unix or Windows format.
- * <p>
- * The prefix length includes the first slash in the full filename
- * if applicable. Thus, it is possible that the length returned is greater
- * than the length of the input string.
- * <pre>
- * Windows:
- * a\b\c.txt --> "" --> relative
- * \a\b\c.txt --> "\" --> current drive absolute
- * C:a\b\c.txt --> "C:" --> drive relative
- * C:\a\b\c.txt --> "C:\" --> absolute
- * \\server\a\b\c.txt --> "\\server\" --> UNC
- *
- * Unix:
- * a/b/c.txt --> "" --> relative
- * /a/b/c.txt --> "/" --> absolute
- * ~/a/b/c.txt --> "~/" --> current user
- * ~ --> "~/" --> current user (slash added)
- * ~user/a/b/c.txt --> "~user/" --> named user
- * ~user --> "~user/" --> named user (slash added)
- * </pre>
- * <p>
- * The output will be the same irrespective of the machine that the code is running on.
- * ie. both Unix and Windows prefixes are matched regardless.
- *
- * @param filename the filename to find the prefix in, null returns -1
- * @return the length of the prefix, -1 if invalid or null
- */
- public static int getPrefixLength(String filename) {
- if (filename == null) {
- return -1;
- }
- int len = filename.length();
- if (len == 0) {
- return 0;
- }
- char ch0 = filename.charAt(0);
- if (ch0 == ':') {
- return -1;
- }
- if (len == 1) {
- if (ch0 == '~') {
- return 2; // return a length greater than the input
- }
- return (isSeparator(ch0) ? 1 : 0);
- } else {
- if (ch0 == '~') {
- int posUnix = filename.indexOf(UNIX_SEPARATOR, 1);
- int posWin = filename.indexOf(WINDOWS_SEPARATOR, 1);
- if (posUnix == -1 && posWin == -1) {
- return len + 1; // return a length greater than the input
- }
- posUnix = (posUnix == -1 ? posWin : posUnix);
- posWin = (posWin == -1 ? posUnix : posWin);
- return Math.min(posUnix, posWin) + 1;
- }
- char ch1 = filename.charAt(1);
- if (ch1 == ':') {
- ch0 = Character.toUpperCase(ch0);
- if (ch0 >= 'A' && ch0 <= 'Z') {
- if (len == 2 || isSeparator(filename.charAt(2)) == false) {
- return 2;
- }
- return 3;
- }
- return -1;
-
- } else if (isSeparator(ch0) && isSeparator(ch1)) {
- int posUnix = filename.indexOf(UNIX_SEPARATOR, 2);
- int posWin = filename.indexOf(WINDOWS_SEPARATOR, 2);
- if ((posUnix == -1 && posWin == -1) || posUnix == 2 || posWin == 2) {
- return -1;
- }
- posUnix = (posUnix == -1 ? posWin : posUnix);
- posWin = (posWin == -1 ? posUnix : posWin);
- return Math.min(posUnix, posWin) + 1;
- } else {
- return (isSeparator(ch0) ? 1 : 0);
- }
- }
- }
-
- /**
- * Returns the index of the last directory separator character.
- * <p>
- * This method will handle a file in either Unix or Windows format.
- * The position of the last forward or backslash is returned.
- * <p>
- * The output will be the same irrespective of the machine that the code is running on.
- *
- * @param filename the filename to find the last path separator in, null returns -1
- * @return the index of the last separator character, or -1 if there
- * is no such character
- */
- public static int indexOfLastSeparator(String filename) {
- if (filename == null) {
- return -1;
- }
- int lastUnixPos = filename.lastIndexOf(UNIX_SEPARATOR);
- int lastWindowsPos = filename.lastIndexOf(WINDOWS_SEPARATOR);
- return Math.max(lastUnixPos, lastWindowsPos);
- }
-
- /**
- * Returns the index of the last extension separator character, which is a dot.
- * <p>
- * This method also checks that there is no directory separator after the last dot.
- * To do this it uses {@link #indexOfLastSeparator(String)} which will
- * handle a file in either Unix or Windows format.
- * <p>
- * The output will be the same irrespective of the machine that the code is running on.
- *
- * @param filename the filename to find the last path separator in, null returns -1
- * @return the index of the last separator character, or -1 if there
- * is no such character
- */
- public static int indexOfExtension(String filename) {
- if (filename == null) {
- return -1;
- }
- int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR);
- int lastSeparator = indexOfLastSeparator(filename);
- return (lastSeparator > extensionPos ? -1 : extensionPos);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets the prefix from a full filename, such as <code>C:/</code>
- * or <code>~/</code>.
- * <p>
- * This method will handle a file in either Unix or Windows format.
- * The prefix includes the first slash in the full filename where applicable.
- * <pre>
- * Windows:
- * a\b\c.txt --> "" --> relative
- * \a\b\c.txt --> "\" --> current drive absolute
- * C:a\b\c.txt --> "C:" --> drive relative
- * C:\a\b\c.txt --> "C:\" --> absolute
- * \\server\a\b\c.txt --> "\\server\" --> UNC
- *
- * Unix:
- * a/b/c.txt --> "" --> relative
- * /a/b/c.txt --> "/" --> absolute
- * ~/a/b/c.txt --> "~/" --> current user
- * ~ --> "~/" --> current user (slash added)
- * ~user/a/b/c.txt --> "~user/" --> named user
- * ~user --> "~user/" --> named user (slash added)
- * </pre>
- * <p>
- * The output will be the same irrespective of the machine that the code is running on.
- * ie. both Unix and Windows prefixes are matched regardless.
- *
- * @param filename the filename to query, null returns null
- * @return the prefix of the file, null if invalid
- */
- public static String getPrefix(String filename) {
- if (filename == null) {
- return null;
- }
- int len = getPrefixLength(filename);
- if (len < 0) {
- return null;
- }
- if (len > filename.length()) {
- return filename + UNIX_SEPARATOR; // we know this only happens for unix
- }
- return filename.substring(0, len);
- }
-
- /**
- * Gets the path from a full filename, which excludes the prefix.
- * <p>
- * This method will handle a file in either Unix or Windows format.
- * The method is entirely text based, and returns the text before and
- * including the last forward or backslash.
- * <pre>
- * C:\a\b\c.txt --> a\b\
- * ~/a/b/c.txt --> a/b/
- * a.txt --> ""
- * a/b/c --> a/b/
- * a/b/c/ --> a/b/c/
- * </pre>
- * <p>
- * The output will be the same irrespective of the machine that the code is running on.
- * <p>
- * This method drops the prefix from the result.
- * See {@link #getFullPath(String)} for the method that retains the prefix.
- *
- * @param filename the filename to query, null returns null
- * @return the path of the file, an empty string if none exists, null if invalid
- */
- public static String getPath(String filename) {
- return doGetPath(filename, 1);
- }
-
- /**
- * Gets the path from a full filename, which excludes the prefix, and
- * also excluding the final directory separator.
- * <p>
- * This method will handle a file in either Unix or Windows format.
- * The method is entirely text based, and returns the text before the
- * last forward or backslash.
- * <pre>
- * C:\a\b\c.txt --> a\b
- * ~/a/b/c.txt --> a/b
- * a.txt --> ""
- * a/b/c --> a/b
- * a/b/c/ --> a/b/c
- * </pre>
- * <p>
- * The output will be the same irrespective of the machine that the code is running on.
- * <p>
- * This method drops the prefix from the result.
- * See {@link #getFullPathNoEndSeparator(String)} for the method that retains the prefix.
- *
- * @param filename the filename to query, null returns null
- * @return the path of the file, an empty string if none exists, null if invalid
- */
- public static String getPathNoEndSeparator(String filename) {
- return doGetPath(filename, 0);
- }
-
- /**
- * Does the work of getting the path.
- *
- * @param filename the filename
- * @param separatorAdd 0 to omit the end separator, 1 to return it
- * @return the path
- */
- private static String doGetPath(String filename, int separatorAdd) {
- if (filename == null) {
- return null;
- }
- int prefix = getPrefixLength(filename);
- if (prefix < 0) {
- return null;
- }
- int index = indexOfLastSeparator(filename);
- if (prefix >= filename.length() || index < 0) {
- return "";
- }
- return filename.substring(prefix, index + separatorAdd);
- }
-
- /**
- * Gets the full path from a full filename, which is the prefix + path.
- * <p>
- * This method will handle a file in either Unix or Windows format.
- * The method is entirely text based, and returns the text before and
- * including the last forward or backslash.
- * <pre>
- * C:\a\b\c.txt --> C:\a\b\
- * ~/a/b/c.txt --> ~/a/b/
- * a.txt --> ""
- * a/b/c --> a/b/
- * a/b/c/ --> a/b/c/
- * C: --> C:
- * C:\ --> C:\
- * ~ --> ~/
- * ~/ --> ~/
- * ~user --> ~user/
- * ~user/ --> ~user/
- * </pre>
- * <p>
- * The output will be the same irrespective of the machine that the code is running on.
- *
- * @param filename the filename to query, null returns null
- * @return the path of the file, an empty string if none exists, null if invalid
- */
- public static String getFullPath(String filename) {
- return doGetFullPath(filename, true);
- }
-
- /**
- * Gets the full path from a full filename, which is the prefix + path,
- * and also excluding the final directory separator.
- * <p>
- * This method will handle a file in either Unix or Windows format.
- * The method is entirely text based, and returns the text before the
- * last forward or backslash.
- * <pre>
- * C:\a\b\c.txt --> C:\a\b
- * ~/a/b/c.txt --> ~/a/b
- * a.txt --> ""
- * a/b/c --> a/b
- * a/b/c/ --> a/b/c
- * C: --> C:
- * C:\ --> C:\
- * ~ --> ~
- * ~/ --> ~
- * ~user --> ~user
- * ~user/ --> ~user
- * </pre>
- * <p>
- * The output will be the same irrespective of the machine that the code is running on.
- *
- * @param filename the filename to query, null returns null
- * @return the path of the file, an empty string if none exists, null if invalid
- */
- public static String getFullPathNoEndSeparator(String filename) {
- return doGetFullPath(filename, false);
- }
-
- /**
- * Does the work of getting the path.
- *
- * @param filename the filename
- * @param includeSeparator true to include the end separator
- * @return the path
- */
- private static String doGetFullPath(String filename, boolean includeSeparator) {
- if (filename == null) {
- return null;
- }
- int prefix = getPrefixLength(filename);
- if (prefix < 0) {
- return null;
- }
- if (prefix >= filename.length()) {
- if (includeSeparator) {
- return getPrefix(filename); // add end slash if necessary
- } else {
- return filename;
- }
- }
- int index = indexOfLastSeparator(filename);
- if (index < 0) {
- return filename.substring(0, prefix);
- }
- int end = index + (includeSeparator ? 1 : 0);
- return filename.substring(0, end);
- }
-
- /**
- * Gets the name minus the path from a full filename.
- * <p>
- * This method will handle a file in either Unix or Windows format.
- * The text after the last forward or backslash is returned.
- * <pre>
- * a/b/c.txt --> c.txt
- * a.txt --> a.txt
- * a/b/c --> c
- * a/b/c/ --> ""
- * </pre>
- * <p>
- * The output will be the same irrespective of the machine that the code is running on.
- *
- * @param filename the filename to query, null returns null
- * @return the name of the file without the path, or an empty string if none exists
- */
- public static String getName(String filename) {
- if (filename == null) {
- return null;
- }
- int index = indexOfLastSeparator(filename);
- return filename.substring(index + 1);
- }
-
- /**
- * Gets the base name, minus the full path and extension, from a full filename.
- * <p>
- * This method will handle a file in either Unix or Windows format.
- * The text after the last forward or backslash and before the last dot is returned.
- * <pre>
- * a/b/c.txt --> c
- * a.txt --> a
- * a/b/c --> c
- * a/b/c/ --> ""
- * </pre>
- * <p>
- * The output will be the same irrespective of the machine that the code is running on.
- *
- * @param filename the filename to query, null returns null
- * @return the name of the file without the path, or an empty string if none exists
- */
- public static String getBaseName(String filename) {
- return removeExtension(getName(filename));
- }
-
- /**
- * Gets the extension of a filename.
- * <p>
- * This method returns the textual part of the filename after the last dot.
- * There must be no directory separator after the dot.
- * <pre>
- * foo.txt --> "txt"
- * a/b/c.jpg --> "jpg"
- * a/b.txt/c --> ""
- * a/b/c --> ""
- * </pre>
- * <p>
- * The output will be the same irrespective of the machine that the code is running on.
- *
- * @param filename the filename to retrieve the extension of.
- * @return the extension of the file or an empty string if none exists.
- */
- public static String getExtension(String filename) {
- if (filename == null) {
- return null;
- }
- int index = indexOfExtension(filename);
- if (index == -1) {
- return "";
- } else {
- return filename.substring(index + 1);
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Removes the extension from a filename.
- * <p>
- * This method returns the textual part of the filename before the last dot.
- * There must be no directory separator after the dot.
- * <pre>
- * foo.txt --> foo
- * a\b\c.jpg --> a\b\c
- * a\b\c --> a\b\c
- * a.b\c --> a.b\c
- * </pre>
- * <p>
- * The output will be the same irrespective of the machine that the code is running on.
- *
- * @param filename the filename to query, null returns null
- * @return the filename minus the extension
- */
- public static String removeExtension(String filename) {
- if (filename == null) {
- return null;
- }
- int index = indexOfExtension(filename);
- if (index == -1) {
- return filename;
- } else {
- return filename.substring(0, index);
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Checks whether two filenames are equal exactly.
- * <p>
- * No processing is performed on the filenames other than comparison,
- * thus this is merely a null-safe case-sensitive equals.
- *
- * @param filename1 the first filename to query, may be null
- * @param filename2 the second filename to query, may be null
- * @return true if the filenames are equal, null equals null
- * @see IOCase#SENSITIVE
- */
- public static boolean equals(String filename1, String filename2) {
- return equals(filename1, filename2, false, IOCase.SENSITIVE);
- }
-
- /**
- * Checks whether two filenames are equal using the case rules of the system.
- * <p>
- * No processing is performed on the filenames other than comparison.
- * The check is case-sensitive on Unix and case-insensitive on Windows.
- *
- * @param filename1 the first filename to query, may be null
- * @param filename2 the second filename to query, may be null
- * @return true if the filenames are equal, null equals null
- * @see IOCase#SYSTEM
- */
- public static boolean equalsOnSystem(String filename1, String filename2) {
- return equals(filename1, filename2, false, IOCase.SYSTEM);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Checks whether two filenames are equal after both have been normalized.
- * <p>
- * Both filenames are first passed to {@link #normalize(String)}.
- * The check is then performed in a case-sensitive manner.
- *
- * @param filename1 the first filename to query, may be null
- * @param filename2 the second filename to query, may be null
- * @return true if the filenames are equal, null equals null
- * @see IOCase#SENSITIVE
- */
- public static boolean equalsNormalized(String filename1, String filename2) {
- return equals(filename1, filename2, true, IOCase.SENSITIVE);
- }
-
- /**
- * Checks whether two filenames are equal after both have been normalized
- * and using the case rules of the system.
- * <p>
- * Both filenames are first passed to {@link #normalize(String)}.
- * The check is then performed case-sensitive on Unix and
- * case-insensitive on Windows.
- *
- * @param filename1 the first filename to query, may be null
- * @param filename2 the second filename to query, may be null
- * @return true if the filenames are equal, null equals null
- * @see IOCase#SYSTEM
- */
- public static boolean equalsNormalizedOnSystem(String filename1, String filename2) {
- return equals(filename1, filename2, true, IOCase.SYSTEM);
- }
-
- /**
- * Checks whether two filenames are equal, optionally normalizing and providing
- * control over the case-sensitivity.
- *
- * @param filename1 the first filename to query, may be null
- * @param filename2 the second filename to query, may be null
- * @param normalized whether to normalize the filenames
- * @param caseSensitivity what case sensitivity rule to use, null means case-sensitive
- * @return true if the filenames are equal, null equals null
- * @since Commons IO 1.3
- */
- public static boolean equals(
- String filename1, String filename2,
- boolean normalized, IOCase caseSensitivity) {
-
- if (filename1 == null || filename2 == null) {
- return filename1 == filename2;
- }
- if (normalized) {
- filename1 = normalize(filename1);
- filename2 = normalize(filename2);
- if (filename1 == null || filename2 == null) {
- throw new NullPointerException(
- "Error normalizing one or both of the file names");
- }
- }
- if (caseSensitivity == null) {
- caseSensitivity = IOCase.SENSITIVE;
- }
- return caseSensitivity.checkEquals(filename1, filename2);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Checks whether the extension of the filename is that specified.
- * <p>
- * This method obtains the extension as the textual part of the filename
- * after the last dot. There must be no directory separator after the dot.
- * The extension check is case-sensitive on all platforms.
- *
- * @param filename the filename to query, null returns false
- * @param extension the extension to check for, null or empty checks for no extension
- * @return true if the filename has the specified extension
- */
- public static boolean isExtension(String filename, String extension) {
- if (filename == null) {
- return false;
- }
- if (extension == null || extension.length() == 0) {
- return (indexOfExtension(filename) == -1);
- }
- String fileExt = getExtension(filename);
- return fileExt.equals(extension);
- }
-
- /**
- * Checks whether the extension of the filename is one of those specified.
- * <p>
- * This method obtains the extension as the textual part of the filename
- * after the last dot. There must be no directory separator after the dot.
- * The extension check is case-sensitive on all platforms.
- *
- * @param filename the filename to query, null returns false
- * @param extensions the extensions to check for, null checks for no extension
- * @return true if the filename is one of the extensions
- */
- public static boolean isExtension(String filename, String[] extensions) {
- if (filename == null) {
- return false;
- }
- if (extensions == null || extensions.length == 0) {
- return (indexOfExtension(filename) == -1);
- }
- String fileExt = getExtension(filename);
- for (int i = 0; i < extensions.length; i++) {
- if (fileExt.equals(extensions[i])) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks whether the extension of the filename is one of those specified.
- * <p>
- * This method obtains the extension as the textual part of the filename
- * after the last dot. There must be no directory separator after the dot.
- * The extension check is case-sensitive on all platforms.
- *
- * @param filename the filename to query, null returns false
- * @param extensions the extensions to check for, null checks for no extension
- * @return true if the filename is one of the extensions
- */
- public static boolean isExtension(String filename, Collection extensions) {
- if (filename == null) {
- return false;
- }
- if (extensions == null || extensions.isEmpty()) {
- return (indexOfExtension(filename) == -1);
- }
- String fileExt = getExtension(filename);
- for (Iterator it = extensions.iterator(); it.hasNext();) {
- if (fileExt.equals(it.next())) {
- return true;
- }
- }
- return false;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Checks a filename to see if it matches the specified wildcard matcher,
- * always testing case-sensitive.
- * <p>
- * The wildcard matcher uses the characters '?' and '*' to represent a
- * single or multiple wildcard characters.
- * This is the same as often found on Dos/Unix command lines.
- * The check is case-sensitive always.
- * <pre>
- * wildcardMatch("c.txt", "*.txt") --> true
- * wildcardMatch("c.txt", "*.jpg") --> false
- * wildcardMatch("a/b/c.txt", "a/b/*") --> true
- * wildcardMatch("c.txt", "*.???") --> true
- * wildcardMatch("c.txt", "*.????") --> false
- * </pre>
- *
- * @param filename the filename to match on
- * @param wildcardMatcher the wildcard string to match against
- * @return true if the filename matches the wilcard string
- * @see IOCase#SENSITIVE
- */
- public static boolean wildcardMatch(String filename, String wildcardMatcher) {
- return wildcardMatch(filename, wildcardMatcher, IOCase.SENSITIVE);
- }
-
- /**
- * Checks a filename to see if it matches the specified wildcard matcher
- * using the case rules of the system.
- * <p>
- * The wildcard matcher uses the characters '?' and '*' to represent a
- * single or multiple wildcard characters.
- * This is the same as often found on Dos/Unix command lines.
- * The check is case-sensitive on Unix and case-insensitive on Windows.
- * <pre>
- * wildcardMatch("c.txt", "*.txt") --> true
- * wildcardMatch("c.txt", "*.jpg") --> false
- * wildcardMatch("a/b/c.txt", "a/b/*") --> true
- * wildcardMatch("c.txt", "*.???") --> true
- * wildcardMatch("c.txt", "*.????") --> false
- * </pre>
- *
- * @param filename the filename to match on
- * @param wildcardMatcher the wildcard string to match against
- * @return true if the filename matches the wilcard string
- * @see IOCase#SYSTEM
- */
- public static boolean wildcardMatchOnSystem(String filename, String wildcardMatcher) {
- return wildcardMatch(filename, wildcardMatcher, IOCase.SYSTEM);
- }
-
- /**
- * Checks a filename to see if it matches the specified wildcard matcher
- * allowing control over case-sensitivity.
- * <p>
- * The wildcard matcher uses the characters '?' and '*' to represent a
- * single or multiple wildcard characters.
- *
- * @param filename the filename to match on
- * @param wildcardMatcher the wildcard string to match against
- * @param caseSensitivity what case sensitivity rule to use, null means case-sensitive
- * @return true if the filename matches the wilcard string
- * @since Commons IO 1.3
- */
- public static boolean wildcardMatch(String filename, String wildcardMatcher, IOCase caseSensitivity) {
- if (filename == null && wildcardMatcher == null) {
- return true;
- }
- if (filename == null || wildcardMatcher == null) {
- return false;
- }
- if (caseSensitivity == null) {
- caseSensitivity = IOCase.SENSITIVE;
- }
- filename = caseSensitivity.convertCase(filename);
- wildcardMatcher = caseSensitivity.convertCase(wildcardMatcher);
- String[] wcs = splitOnTokens(wildcardMatcher);
- boolean anyChars = false;
- int textIdx = 0;
- int wcsIdx = 0;
- Stack backtrack = new Stack();
-
- // loop around a backtrack stack, to handle complex * matching
- do {
- if (backtrack.size() > 0) {
- int[] array = (int[]) backtrack.pop();
- wcsIdx = array[0];
- textIdx = array[1];
- anyChars = true;
- }
-
- // loop whilst tokens and text left to process
- while (wcsIdx < wcs.length) {
-
- if (wcs[wcsIdx].equals("?")) {
- // ? so move to next text char
- textIdx++;
- anyChars = false;
-
- } else if (wcs[wcsIdx].equals("*")) {
- // set any chars status
- anyChars = true;
- if (wcsIdx == wcs.length - 1) {
- textIdx = filename.length();
- }
-
- } else {
- // matching text token
- if (anyChars) {
- // any chars then try to locate text token
- textIdx = filename.indexOf(wcs[wcsIdx], textIdx);
- if (textIdx == -1) {
- // token not found
- break;
- }
- int repeat = filename.indexOf(wcs[wcsIdx], textIdx + 1);
- if (repeat >= 0) {
- backtrack.push(new int[] {wcsIdx, repeat});
- }
- } else {
- // matching from current position
- if (!filename.startsWith(wcs[wcsIdx], textIdx)) {
- // couldnt match token
- break;
- }
- }
-
- // matched text token, move text index to end of matched token
- textIdx += wcs[wcsIdx].length();
- anyChars = false;
- }
-
- wcsIdx++;
- }
-
- // full match
- if (wcsIdx == wcs.length && textIdx == filename.length()) {
- return true;
- }
-
- } while (backtrack.size() > 0);
-
- return false;
- }
-
- /**
- * Splits a string into a number of tokens.
- *
- * @param text the text to split
- * @return the tokens, never null
- */
- static String[] splitOnTokens(String text) {
- // used by wildcardMatch
- // package level so a unit test may run on this
-
- if (text.indexOf("?") == -1 && text.indexOf("*") == -1) {
- return new String[] { text };
- }
-
- char[] array = text.toCharArray();
- ArrayList list = new ArrayList();
- StringBuffer buffer = new StringBuffer();
- for (int i = 0; i < array.length; i++) {
- if (array[i] == '?' || array[i] == '*') {
- if (buffer.length() != 0) {
- list.add(buffer.toString());
- buffer.setLength(0);
- }
- if (array[i] == '?') {
- list.add("?");
- } else if (list.size() == 0 ||
- (i > 0 && list.get(list.size() - 1).equals("*") == false)) {
- list.add("*");
- }
- } else {
- buffer.append(array[i]);
- }
- }
- if (buffer.length() != 0) {
- list.add(buffer.toString());
- }
-
- return (String[]) list.toArray( new String[ list.size() ] );
- }
-
-}
diff --git a/src/org/apache/commons/io/HexDump.java b/src/org/apache/commons/io/HexDump.java
deleted file mode 100644
index b0d468d18..000000000
--- a/src/org/apache/commons/io/HexDump.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Dumps data in hexadecimal format.
- * <p>
- * Provides a single function to take an array of bytes and display it
- * in hexadecimal form.
- * <p>
- * Origin of code: POI.
- *
- * @author Scott Sanders
- * @author Marc Johnson
- * @version $Id: HexDump.java 596667 2007-11-20 13:50:14Z niallp $
- */
-public class HexDump {
-
- /**
- * Instances should NOT be constructed in standard programming.
- */
- public HexDump() {
- super();
- }
-
- /**
- * Dump an array of bytes to an OutputStream.
- *
- * @param data the byte array to be dumped
- * @param offset its offset, whatever that might mean
- * @param stream the OutputStream to which the data is to be
- * written
- * @param index initial index into the byte array
- *
- * @throws IOException is thrown if anything goes wrong writing
- * the data to stream
- * @throws ArrayIndexOutOfBoundsException if the index is
- * outside the data array's bounds
- * @throws IllegalArgumentException if the output stream is null
- */
-
- public static void dump(byte[] data, long offset,
- OutputStream stream, int index)
- throws IOException, ArrayIndexOutOfBoundsException,
- IllegalArgumentException {
-
- if ((index < 0) || (index >= data.length)) {
- throw new ArrayIndexOutOfBoundsException(
- "illegal index: " + index + " into array of length "
- + data.length);
- }
- if (stream == null) {
- throw new IllegalArgumentException("cannot write to nullstream");
- }
- long display_offset = offset + index;
- StringBuffer buffer = new StringBuffer(74);
-
- for (int j = index; j < data.length; j += 16) {
- int chars_read = data.length - j;
-
- if (chars_read > 16) {
- chars_read = 16;
- }
- dump(buffer, display_offset).append(' ');
- for (int k = 0; k < 16; k++) {
- if (k < chars_read) {
- dump(buffer, data[k + j]);
- } else {
- buffer.append(" ");
- }
- buffer.append(' ');
- }
- for (int k = 0; k < chars_read; k++) {
- if ((data[k + j] >= ' ') && (data[k + j] < 127)) {
- buffer.append((char) data[k + j]);
- } else {
- buffer.append('.');
- }
- }
- buffer.append(EOL);
- stream.write(buffer.toString().getBytes());
- stream.flush();
- buffer.setLength(0);
- display_offset += chars_read;
- }
- }
-
- /**
- * The line-separator (initializes to "line.separator" system property.
- */
- public static final String EOL =
- System.getProperty("line.separator");
- private static final char[] _hexcodes =
- {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'A', 'B', 'C', 'D', 'E', 'F'
- };
- private static final int[] _shifts =
- {
- 28, 24, 20, 16, 12, 8, 4, 0
- };
-
- /**
- * Dump a long value into a StringBuffer.
- *
- * @param _lbuffer the StringBuffer to dump the value in
- * @param value the long value to be dumped
- * @return StringBuffer containing the dumped value.
- */
- private static StringBuffer dump(StringBuffer _lbuffer, long value) {
- for (int j = 0; j < 8; j++) {
- _lbuffer
- .append(_hexcodes[((int) (value >> _shifts[j])) & 15]);
- }
- return _lbuffer;
- }
-
- /**
- * Dump a byte value into a StringBuffer.
- *
- * @param _cbuffer the StringBuffer to dump the value in
- * @param value the byte value to be dumped
- * @return StringBuffer containing the dumped value.
- */
- private static StringBuffer dump(StringBuffer _cbuffer, byte value) {
- for (int j = 0; j < 2; j++) {
- _cbuffer.append(_hexcodes[(value >> _shifts[j + 6]) & 15]);
- }
- return _cbuffer;
- }
-
-}
diff --git a/src/org/apache/commons/io/IOCase.java b/src/org/apache/commons/io/IOCase.java
deleted file mode 100644
index 4230f450d..000000000
--- a/src/org/apache/commons/io/IOCase.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io;
-
-import java.io.Serializable;
-
-/**
- * Enumeration of IO case sensitivity.
- * <p>
- * Different filing systems have different rules for case-sensitivity.
- * Windows is case-insensitive, Unix is case-sensitive.
- * <p>
- * This class captures that difference, providing an enumeration to
- * control how filename comparisons should be performed. It also provides
- * methods that use the enumeration to perform comparisons.
- * <p>
- * Wherever possible, you should use the <code>check</code> methods in this
- * class to compare filenames.
- *
- * @author Stephen Colebourne
- * @version $Id: IOCase.java 606345 2007-12-21 23:43:01Z ggregory $
- * @since Commons IO 1.3
- */
-public final class IOCase implements Serializable {
-
- /**
- * The constant for case sensitive regardless of operating system.
- */
- public static final IOCase SENSITIVE = new IOCase("Sensitive", true);
-
- /**
- * The constant for case insensitive regardless of operating system.
- */
- public static final IOCase INSENSITIVE = new IOCase("Insensitive", false);
-
- /**
- * The constant for case sensitivity determined by the current operating system.
- * Windows is case-insensitive when comparing filenames, Unix is case-sensitive.
- * <p>
- * If you derialize this constant of Windows, and deserialize on Unix, or vice
- * versa, then the value of the case-sensitivity flag will change.
- */
- public static final IOCase SYSTEM = new IOCase("System", !FilenameUtils.isSystemWindows());
-
- /** Serialization version. */
- private static final long serialVersionUID = -6343169151696340687L;
-
- /** The enumeration name. */
- private final String name;
-
- /** The sensitivity flag. */
- private final transient boolean sensitive;
-
- //-----------------------------------------------------------------------
- /**
- * Factory method to create an IOCase from a name.
- *
- * @param name the name to find
- * @return the IOCase object
- * @throws IllegalArgumentException if the name is invalid
- */
- public static IOCase forName(String name) {
- if (IOCase.SENSITIVE.name.equals(name)){
- return IOCase.SENSITIVE;
- }
- if (IOCase.INSENSITIVE.name.equals(name)){
- return IOCase.INSENSITIVE;
- }
- if (IOCase.SYSTEM.name.equals(name)){
- return IOCase.SYSTEM;
- }
- throw new IllegalArgumentException("Invalid IOCase name: " + name);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Private constructor.
- *
- * @param name the name
- * @param sensitive the sensitivity
- */
- private IOCase(String name, boolean sensitive) {
- this.name = name;
- this.sensitive = sensitive;
- }
-
- /**
- * Replaces the enumeration from the stream with a real one.
- * This ensures that the correct flag is set for SYSTEM.
- *
- * @return the resolved object
- */
- private Object readResolve() {
- return forName(name);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets the name of the constant.
- *
- * @return the name of the constant
- */
- public String getName() {
- return name;
- }
-
- /**
- * Does the object represent case sensitive comparison.
- *
- * @return true if case sensitive
- */
- public boolean isCaseSensitive() {
- return sensitive;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Compares two strings using the case-sensitivity rule.
- * <p>
- * This method mimics {@link String#compareTo} but takes case-sensitivity
- * into account.
- *
- * @param str1 the first string to compare, not null
- * @param str2 the second string to compare, not null
- * @return true if equal using the case rules
- * @throws NullPointerException if either string is null
- */
- public int checkCompareTo(String str1, String str2) {
- if (str1 == null || str2 == null) {
- throw new NullPointerException("The strings must not be null");
- }
- return sensitive ? str1.compareTo(str2) : str1.compareToIgnoreCase(str2);
- }
-
- /**
- * Compares two strings using the case-sensitivity rule.
- * <p>
- * This method mimics {@link String#equals} but takes case-sensitivity
- * into account.
- *
- * @param str1 the first string to compare, not null
- * @param str2 the second string to compare, not null
- * @return true if equal using the case rules
- * @throws NullPointerException if either string is null
- */
- public boolean checkEquals(String str1, String str2) {
- if (str1 == null || str2 == null) {
- throw new NullPointerException("The strings must not be null");
- }
- return sensitive ? str1.equals(str2) : str1.equalsIgnoreCase(str2);
- }
-
- /**
- * Checks if one string starts with another using the case-sensitivity rule.
- * <p>
- * This method mimics {@link String#startsWith(String)} but takes case-sensitivity
- * into account.
- *
- * @param str the string to check, not null
- * @param start the start to compare against, not null
- * @return true if equal using the case rules
- * @throws NullPointerException if either string is null
- */
- public boolean checkStartsWith(String str, String start) {
- return str.regionMatches(!sensitive, 0, start, 0, start.length());
- }
-
- /**
- * Checks if one string ends with another using the case-sensitivity rule.
- * <p>
- * This method mimics {@link String#endsWith} but takes case-sensitivity
- * into account.
- *
- * @param str the string to check, not null
- * @param end the end to compare against, not null
- * @return true if equal using the case rules
- * @throws NullPointerException if either string is null
- */
- public boolean checkEndsWith(String str, String end) {
- int endLen = end.length();
- return str.regionMatches(!sensitive, str.length() - endLen, end, 0, endLen);
- }
-
- /**
- * Checks if one string contains another at a specific index using the case-sensitivity rule.
- * <p>
- * This method mimics parts of {@link String#regionMatches(boolean, int, String, int, int)}
- * but takes case-sensitivity into account.
- *
- * @param str the string to check, not null
- * @param strStartIndex the index to start at in str
- * @param search the start to search for, not null
- * @return true if equal using the case rules
- * @throws NullPointerException if either string is null
- */
- public boolean checkRegionMatches(String str, int strStartIndex, String search) {
- return str.regionMatches(!sensitive, strStartIndex, search, 0, search.length());
- }
-
- /**
- * Converts the case of the input String to a standard format.
- * Subsequent operations can then use standard String methods.
- *
- * @param str the string to convert, null returns null
- * @return the lower-case version if case-insensitive
- */
- String convertCase(String str) {
- if (str == null) {
- return null;
- }
- return sensitive ? str : str.toLowerCase();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets a string describing the sensitivity.
- *
- * @return a string describing the sensitivity
- */
- public String toString() {
- return name;
- }
-
-}
diff --git a/src/org/apache/commons/io/IOExceptionWithCause.java b/src/org/apache/commons/io/IOExceptionWithCause.java
deleted file mode 100644
index a15815a22..000000000
--- a/src/org/apache/commons/io/IOExceptionWithCause.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.io;
-
-import java.io.IOException;
-
-/**
- * Subclasses IOException with the {@link Throwable} constructors missing before Java 6. If you are using Java 6,
- * consider this class deprecated and use {@link IOException}.
- *
- * @author <a href="http://commons.apache.org/io/">Apache Commons IO</a>
- * @version $Id$
- * @since Commons IO 1.4
- */
-public class IOExceptionWithCause extends IOException {
-
- /**
- * Defines the serial version UID.
- */
- private static final long serialVersionUID = 1L;
-
- /**
- * Constructs a new instance with the given message and cause.
- * <p>
- * As specified in {@link Throwable}, the message in the given <code>cause</code> is not used in this instance's
- * message.
- * </p>
- *
- * @param message
- * the message (see {@link #getMessage()})
- * @param cause
- * the cause (see {@link #getCause()}). A <code>null</code> value is allowed.
- */
- public IOExceptionWithCause(String message, Throwable cause) {
- super(message);
- this.initCause(cause);
- }
-
- /**
- * Constructs a new instance with the given cause.
- * <p>
- * The message is set to <code>cause==null ? null : cause.toString()</code>, which by default contains the class
- * and message of <code>cause</code>. This constructor is useful for call sites that just wrap another throwable.
- * </p>
- *
- * @param cause
- * the cause (see {@link #getCause()}). A <code>null</code> value is allowed.
- */
- public IOExceptionWithCause(Throwable cause) {
- super(cause == null ? null : cause.toString());
- this.initCause(cause);
- }
-
-}
diff --git a/src/org/apache/commons/io/IOUtils.java b/src/org/apache/commons/io/IOUtils.java
deleted file mode 100644
index 1f91e2562..000000000
--- a/src/org/apache/commons/io/IOUtils.java
+++ /dev/null
@@ -1,1274 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.CharArrayWriter;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.commons.io.output.ByteArrayOutputStream;
-
-/**
- * General IO stream manipulation utilities.
- * <p>
- * This class provides static utility methods for input/output operations.
- * <ul>
- * <li>closeQuietly - these methods close a stream ignoring nulls and exceptions
- * <li>toXxx/read - these methods read data from a stream
- * <li>write - these methods write data to a stream
- * <li>copy - these methods copy all the data from one stream to another
- * <li>contentEquals - these methods compare the content of two streams
- * </ul>
- * <p>
- * The byte-to-char methods and char-to-byte methods involve a conversion step.
- * Two methods are provided in each case, one that uses the platform default
- * encoding and the other which allows you to specify an encoding. You are
- * encouraged to always specify an encoding because relying on the platform
- * default can lead to unexpected results, for example when moving from
- * development to production.
- * <p>
- * All the methods in this class that read a stream are buffered internally.
- * This means that there is no cause to use a <code>BufferedInputStream</code>
- * or <code>BufferedReader</code>. The default buffer size of 4K has been shown
- * to be efficient in tests.
- * <p>
- * Wherever possible, the methods in this class do <em>not</em> flush or close
- * the stream. This is to avoid making non-portable assumptions about the
- * streams' origin and further use. Thus the caller is still responsible for
- * closing streams after use.
- * <p>
- * Origin of code: Excalibur.
- *
- * @author Peter Donald
- * @author Jeff Turner
- * @author Matthew Hawthorne
- * @author Stephen Colebourne
- * @author Gareth Davis
- * @author Ian Springer
- * @author Niall Pemberton
- * @author Sandy McArthur
- * @version $Id: IOUtils.java 481854 2006-12-03 18:30:07Z scolebourne $
- */
-public class IOUtils {
- // NOTE: This class is focussed on InputStream, OutputStream, Reader and
- // Writer. Each method should take at least one of these as a parameter,
- // or return one of them.
-
- /**
- * The Unix directory separator character.
- */
- public static final char DIR_SEPARATOR_UNIX = '/';
- /**
- * The Windows directory separator character.
- */
- public static final char DIR_SEPARATOR_WINDOWS = '\\';
- /**
- * The system directory separator character.
- */
- public static final char DIR_SEPARATOR = File.separatorChar;
- /**
- * The Unix line separator string.
- */
- public static final String LINE_SEPARATOR_UNIX = "\n";
- /**
- * The Windows line separator string.
- */
- public static final String LINE_SEPARATOR_WINDOWS = "\r\n";
- /**
- * The system line separator string.
- */
- public static final String LINE_SEPARATOR;
- static {
- // avoid security issues
- StringWriter buf = new StringWriter(4);
- PrintWriter out = new PrintWriter(buf);
- out.println();
- LINE_SEPARATOR = buf.toString();
- }
-
- /**
- * The default buffer size to use.
- */
- private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
-
- /**
- * Instances should NOT be constructed in standard programming.
- */
- public IOUtils() {
- super();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Unconditionally close an <code>Reader</code>.
- * <p>
- * Equivalent to {@link Reader#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
- *
- * @param input the Reader to close, may be null or already closed
- */
- public static void closeQuietly(Reader input) {
- try {
- if (input != null) {
- input.close();
- }
- } catch (IOException ioe) {
- // ignore
- }
- }
-
- /**
- * Unconditionally close a <code>Writer</code>.
- * <p>
- * Equivalent to {@link Writer#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
- *
- * @param output the Writer to close, may be null or already closed
- */
- public static void closeQuietly(Writer output) {
- try {
- if (output != null) {
- output.close();
- }
- } catch (IOException ioe) {
- // ignore
- }
- }
-
- /**
- * Unconditionally close an <code>InputStream</code>.
- * <p>
- * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
- *
- * @param input the InputStream to close, may be null or already closed
- */
- public static void closeQuietly(InputStream input) {
- try {
- if (input != null) {
- input.close();
- }
- } catch (IOException ioe) {
- // ignore
- }
- }
-
- /**
- * Unconditionally close an <code>OutputStream</code>.
- * <p>
- * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
- *
- * @param output the OutputStream to close, may be null or already closed
- */
- public static void closeQuietly(OutputStream output) {
- try {
- if (output != null) {
- output.close();
- }
- } catch (IOException ioe) {
- // ignore
- }
- }
-
- // read toByteArray
- //-----------------------------------------------------------------------
- /**
- * Get the contents of an <code>InputStream</code> as a <code>byte[]</code>.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedInputStream</code>.
- *
- * @param input the <code>InputStream</code> to read from
- * @return the requested byte array
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- */
- public static byte[] toByteArray(InputStream input) throws IOException {
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- copy(input, output);
- return output.toByteArray();
- }
-
- /**
- * Get the contents of a <code>Reader</code> as a <code>byte[]</code>
- * using the default character encoding of the platform.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedReader</code>.
- *
- * @param input the <code>Reader</code> to read from
- * @return the requested byte array
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- */
- public static byte[] toByteArray(Reader input) throws IOException {
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- copy(input, output);
- return output.toByteArray();
- }
-
- /**
- * Get the contents of a <code>Reader</code> as a <code>byte[]</code>
- * using the specified character encoding.
- * <p>
- * Character encoding names can be found at
- * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedReader</code>.
- *
- * @param input the <code>Reader</code> to read from
- * @param encoding the encoding to use, null means platform default
- * @return the requested byte array
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static byte[] toByteArray(Reader input, String encoding)
- throws IOException {
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- copy(input, output, encoding);
- return output.toByteArray();
- }
-
- /**
- * Get the contents of a <code>String</code> as a <code>byte[]</code>
- * using the default character encoding of the platform.
- * <p>
- * This is the same as {@link String#getBytes()}.
- *
- * @param input the <code>String</code> to convert
- * @return the requested byte array
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs (never occurs)
- * @deprecated Use {@link String#getBytes()}
- */
- public static byte[] toByteArray(String input) throws IOException {
- return input.getBytes();
- }
-
- // read char[]
- //-----------------------------------------------------------------------
- /**
- * Get the contents of an <code>InputStream</code> as a character array
- * using the default character encoding of the platform.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedInputStream</code>.
- *
- * @param is the <code>InputStream</code> to read from
- * @return the requested character array
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static char[] toCharArray(InputStream is) throws IOException {
- CharArrayWriter output = new CharArrayWriter();
- copy(is, output);
- return output.toCharArray();
- }
-
- /**
- * Get the contents of an <code>InputStream</code> as a character array
- * using the specified character encoding.
- * <p>
- * Character encoding names can be found at
- * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedInputStream</code>.
- *
- * @param is the <code>InputStream</code> to read from
- * @param encoding the encoding to use, null means platform default
- * @return the requested character array
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static char[] toCharArray(InputStream is, String encoding)
- throws IOException {
- CharArrayWriter output = new CharArrayWriter();
- copy(is, output, encoding);
- return output.toCharArray();
- }
-
- /**
- * Get the contents of a <code>Reader</code> as a character array.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedReader</code>.
- *
- * @param input the <code>Reader</code> to read from
- * @return the requested character array
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static char[] toCharArray(Reader input) throws IOException {
- CharArrayWriter sw = new CharArrayWriter();
- copy(input, sw);
- return sw.toCharArray();
- }
-
- // read toString
- //-----------------------------------------------------------------------
- /**
- * Get the contents of an <code>InputStream</code> as a String
- * using the default character encoding of the platform.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedInputStream</code>.
- *
- * @param input the <code>InputStream</code> to read from
- * @return the requested String
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- */
- public static String toString(InputStream input) throws IOException {
- StringWriter sw = new StringWriter();
- copy(input, sw);
- return sw.toString();
- }
-
- /**
- * Get the contents of an <code>InputStream</code> as a String
- * using the specified character encoding.
- * <p>
- * Character encoding names can be found at
- * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedInputStream</code>.
- *
- * @param input the <code>InputStream</code> to read from
- * @param encoding the encoding to use, null means platform default
- * @return the requested String
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- */
- public static String toString(InputStream input, String encoding)
- throws IOException {
- StringWriter sw = new StringWriter();
- copy(input, sw, encoding);
- return sw.toString();
- }
-
- /**
- * Get the contents of a <code>Reader</code> as a String.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedReader</code>.
- *
- * @param input the <code>Reader</code> to read from
- * @return the requested String
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- */
- public static String toString(Reader input) throws IOException {
- StringWriter sw = new StringWriter();
- copy(input, sw);
- return sw.toString();
- }
-
- /**
- * Get the contents of a <code>byte[]</code> as a String
- * using the default character encoding of the platform.
- *
- * @param input the byte array to read from
- * @return the requested String
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs (never occurs)
- * @deprecated Use {@link String#String(byte[])}
- */
- public static String toString(byte[] input) throws IOException {
- return new String(input);
- }
-
- /**
- * Get the contents of a <code>byte[]</code> as a String
- * using the specified character encoding.
- * <p>
- * Character encoding names can be found at
- * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
- *
- * @param input the byte array to read from
- * @param encoding the encoding to use, null means platform default
- * @return the requested String
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs (never occurs)
- * @deprecated Use {@link String#String(byte[],String)}
- */
- public static String toString(byte[] input, String encoding)
- throws IOException {
- if (encoding == null) {
- return new String(input);
- } else {
- return new String(input, encoding);
- }
- }
-
- // readLines
- //-----------------------------------------------------------------------
- /**
- * Get the contents of an <code>InputStream</code> as a list of Strings,
- * one entry per line, using the default character encoding of the platform.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedInputStream</code>.
- *
- * @param input the <code>InputStream</code> to read from, not null
- * @return the list of Strings, never null
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static List readLines(InputStream input) throws IOException {
- InputStreamReader reader = new InputStreamReader(input);
- return readLines(reader);
- }
-
- /**
- * Get the contents of an <code>InputStream</code> as a list of Strings,
- * one entry per line, using the specified character encoding.
- * <p>
- * Character encoding names can be found at
- * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedInputStream</code>.
- *
- * @param input the <code>InputStream</code> to read from, not null
- * @param encoding the encoding to use, null means platform default
- * @return the list of Strings, never null
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static List readLines(InputStream input, String encoding) throws IOException {
- if (encoding == null) {
- return readLines(input);
- } else {
- InputStreamReader reader = new InputStreamReader(input, encoding);
- return readLines(reader);
- }
- }
-
- /**
- * Get the contents of a <code>Reader</code> as a list of Strings,
- * one entry per line.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedReader</code>.
- *
- * @param input the <code>Reader</code> to read from, not null
- * @return the list of Strings, never null
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static List readLines(Reader input) throws IOException {
- BufferedReader reader = new BufferedReader(input);
- List list = new ArrayList();
- String line = reader.readLine();
- while (line != null) {
- list.add(line);
- line = reader.readLine();
- }
- return list;
- }
-
- // lineIterator
- //-----------------------------------------------------------------------
- /**
- * Return an Iterator for the lines in a <code>Reader</code>.
- * <p>
- * <code>LineIterator</code> holds a reference to the open
- * <code>Reader</code> specified here. When you have finished with the
- * iterator you should close the reader to free internal resources.
- * This can be done by closing the reader directly, or by calling
- * {@link LineIterator#close()} or {@link LineIterator#closeQuietly(LineIterator)}.
- * <p>
- * The recommended usage pattern is:
- * <pre>
- * try {
- * LineIterator it = IOUtils.lineIterator(reader);
- * while (it.hasNext()) {
- * String line = it.nextLine();
- * /// do something with line
- * }
- * } finally {
- * IOUtils.closeQuietly(reader);
- * }
- * </pre>
- *
- * @param reader the <code>Reader</code> to read from, not null
- * @return an Iterator of the lines in the reader, never null
- * @throws IllegalArgumentException if the reader is null
- * @since Commons IO 1.2
- */
- public static LineIterator lineIterator(Reader reader) {
- return new LineIterator(reader);
- }
-
- /**
- * Return an Iterator for the lines in an <code>InputStream</code>, using
- * the character encoding specified (or default encoding if null).
- * <p>
- * <code>LineIterator</code> holds a reference to the open
- * <code>InputStream</code> specified here. When you have finished with
- * the iterator you should close the stream to free internal resources.
- * This can be done by closing the stream directly, or by calling
- * {@link LineIterator#close()} or {@link LineIterator#closeQuietly(LineIterator)}.
- * <p>
- * The recommended usage pattern is:
- * <pre>
- * try {
- * LineIterator it = IOUtils.lineIterator(stream, "UTF-8");
- * while (it.hasNext()) {
- * String line = it.nextLine();
- * /// do something with line
- * }
- * } finally {
- * IOUtils.closeQuietly(stream);
- * }
- * </pre>
- *
- * @param input the <code>InputStream</code> to read from, not null
- * @param encoding the encoding to use, null means platform default
- * @return an Iterator of the lines in the reader, never null
- * @throws IllegalArgumentException if the input is null
- * @throws IOException if an I/O error occurs, such as if the encoding is invalid
- * @since Commons IO 1.2
- */
- public static LineIterator lineIterator(InputStream input, String encoding)
- throws IOException {
- Reader reader = null;
- if (encoding == null) {
- reader = new InputStreamReader(input);
- } else {
- reader = new InputStreamReader(input, encoding);
- }
- return new LineIterator(reader);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Convert the specified string to an input stream, encoded as bytes
- * using the default character encoding of the platform.
- *
- * @param input the string to convert
- * @return an input stream
- * @since Commons IO 1.1
- */
- public static InputStream toInputStream(String input) {
- byte[] bytes = input.getBytes();
- return new ByteArrayInputStream(bytes);
- }
-
- /**
- * Convert the specified string to an input stream, encoded as bytes
- * using the specified character encoding.
- * <p>
- * Character encoding names can be found at
- * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
- *
- * @param input the string to convert
- * @param encoding the encoding to use, null means platform default
- * @throws IOException if the encoding is invalid
- * @return an input stream
- * @since Commons IO 1.1
- */
- public static InputStream toInputStream(String input, String encoding) throws IOException {
- byte[] bytes = encoding != null ? input.getBytes(encoding) : input.getBytes();
- return new ByteArrayInputStream(bytes);
- }
-
- // write byte[]
- //-----------------------------------------------------------------------
- /**
- * Writes bytes from a <code>byte[]</code> to an <code>OutputStream</code>.
- *
- * @param data the byte array to write, do not modify during output,
- * null ignored
- * @param output the <code>OutputStream</code> to write to
- * @throws NullPointerException if output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void write(byte[] data, OutputStream output)
- throws IOException {
- if (data != null) {
- output.write(data);
- }
- }
-
- /**
- * Writes bytes from a <code>byte[]</code> to chars on a <code>Writer</code>
- * using the default character encoding of the platform.
- * <p>
- * This method uses {@link String#String(byte[])}.
- *
- * @param data the byte array to write, do not modify during output,
- * null ignored
- * @param output the <code>Writer</code> to write to
- * @throws NullPointerException if output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void write(byte[] data, Writer output) throws IOException {
- if (data != null) {
- output.write(new String(data));
- }
- }
-
- /**
- * Writes bytes from a <code>byte[]</code> to chars on a <code>Writer</code>
- * using the specified character encoding.
- * <p>
- * Character encoding names can be found at
- * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
- * <p>
- * This method uses {@link String#String(byte[], String)}.
- *
- * @param data the byte array to write, do not modify during output,
- * null ignored
- * @param output the <code>Writer</code> to write to
- * @param encoding the encoding to use, null means platform default
- * @throws NullPointerException if output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void write(byte[] data, Writer output, String encoding)
- throws IOException {
- if (data != null) {
- if (encoding == null) {
- write(data, output);
- } else {
- output.write(new String(data, encoding));
- }
- }
- }
-
- // write char[]
- //-----------------------------------------------------------------------
- /**
- * Writes chars from a <code>char[]</code> to a <code>Writer</code>
- * using the default character encoding of the platform.
- *
- * @param data the char array to write, do not modify during output,
- * null ignored
- * @param output the <code>Writer</code> to write to
- * @throws NullPointerException if output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void write(char[] data, Writer output) throws IOException {
- if (data != null) {
- output.write(data);
- }
- }
-
- /**
- * Writes chars from a <code>char[]</code> to bytes on an
- * <code>OutputStream</code>.
- * <p>
- * This method uses {@link String#String(char[])} and
- * {@link String#getBytes()}.
- *
- * @param data the char array to write, do not modify during output,
- * null ignored
- * @param output the <code>OutputStream</code> to write to
- * @throws NullPointerException if output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void write(char[] data, OutputStream output)
- throws IOException {
- if (data != null) {
- output.write(new String(data).getBytes());
- }
- }
-
- /**
- * Writes chars from a <code>char[]</code> to bytes on an
- * <code>OutputStream</code> using the specified character encoding.
- * <p>
- * Character encoding names can be found at
- * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
- * <p>
- * This method uses {@link String#String(char[])} and
- * {@link String#getBytes(String)}.
- *
- * @param data the char array to write, do not modify during output,
- * null ignored
- * @param output the <code>OutputStream</code> to write to
- * @param encoding the encoding to use, null means platform default
- * @throws NullPointerException if output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void write(char[] data, OutputStream output, String encoding)
- throws IOException {
- if (data != null) {
- if (encoding == null) {
- write(data, output);
- } else {
- output.write(new String(data).getBytes(encoding));
- }
- }
- }
-
- // write String
- //-----------------------------------------------------------------------
- /**
- * Writes chars from a <code>String</code> to a <code>Writer</code>.
- *
- * @param data the <code>String</code> to write, null ignored
- * @param output the <code>Writer</code> to write to
- * @throws NullPointerException if output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void write(String data, Writer output) throws IOException {
- if (data != null) {
- output.write(data);
- }
- }
-
- /**
- * Writes chars from a <code>String</code> to bytes on an
- * <code>OutputStream</code> using the default character encoding of the
- * platform.
- * <p>
- * This method uses {@link String#getBytes()}.
- *
- * @param data the <code>String</code> to write, null ignored
- * @param output the <code>OutputStream</code> to write to
- * @throws NullPointerException if output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void write(String data, OutputStream output)
- throws IOException {
- if (data != null) {
- output.write(data.getBytes());
- }
- }
-
- /**
- * Writes chars from a <code>String</code> to bytes on an
- * <code>OutputStream</code> using the specified character encoding.
- * <p>
- * Character encoding names can be found at
- * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
- * <p>
- * This method uses {@link String#getBytes(String)}.
- *
- * @param data the <code>String</code> to write, null ignored
- * @param output the <code>OutputStream</code> to write to
- * @param encoding the encoding to use, null means platform default
- * @throws NullPointerException if output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void write(String data, OutputStream output, String encoding)
- throws IOException {
- if (data != null) {
- if (encoding == null) {
- write(data, output);
- } else {
- output.write(data.getBytes(encoding));
- }
- }
- }
-
- // write StringBuffer
- //-----------------------------------------------------------------------
- /**
- * Writes chars from a <code>StringBuffer</code> to a <code>Writer</code>.
- *
- * @param data the <code>StringBuffer</code> to write, null ignored
- * @param output the <code>Writer</code> to write to
- * @throws NullPointerException if output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void write(StringBuffer data, Writer output)
- throws IOException {
- if (data != null) {
- output.write(data.toString());
- }
- }
-
- /**
- * Writes chars from a <code>StringBuffer</code> to bytes on an
- * <code>OutputStream</code> using the default character encoding of the
- * platform.
- * <p>
- * This method uses {@link String#getBytes()}.
- *
- * @param data the <code>StringBuffer</code> to write, null ignored
- * @param output the <code>OutputStream</code> to write to
- * @throws NullPointerException if output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void write(StringBuffer data, OutputStream output)
- throws IOException {
- if (data != null) {
- output.write(data.toString().getBytes());
- }
- }
-
- /**
- * Writes chars from a <code>StringBuffer</code> to bytes on an
- * <code>OutputStream</code> using the specified character encoding.
- * <p>
- * Character encoding names can be found at
- * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
- * <p>
- * This method uses {@link String#getBytes(String)}.
- *
- * @param data the <code>StringBuffer</code> to write, null ignored
- * @param output the <code>OutputStream</code> to write to
- * @param encoding the encoding to use, null means platform default
- * @throws NullPointerException if output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void write(StringBuffer data, OutputStream output,
- String encoding) throws IOException {
- if (data != null) {
- if (encoding == null) {
- write(data, output);
- } else {
- output.write(data.toString().getBytes(encoding));
- }
- }
- }
-
- // writeLines
- //-----------------------------------------------------------------------
- /**
- * Writes the <code>toString()</code> value of each item in a collection to
- * an <code>OutputStream</code> line by line, using the default character
- * encoding of the platform and the specified line ending.
- *
- * @param lines the lines to write, null entries produce blank lines
- * @param lineEnding the line separator to use, null is system default
- * @param output the <code>OutputStream</code> to write to, not null, not closed
- * @throws NullPointerException if the output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void writeLines(Collection lines, String lineEnding,
- OutputStream output) throws IOException {
- if (lines == null) {
- return;
- }
- if (lineEnding == null) {
- lineEnding = LINE_SEPARATOR;
- }
- for (Iterator it = lines.iterator(); it.hasNext(); ) {
- Object line = it.next();
- if (line != null) {
- output.write(line.toString().getBytes());
- }
- output.write(lineEnding.getBytes());
- }
- }
-
- /**
- * Writes the <code>toString()</code> value of each item in a collection to
- * an <code>OutputStream</code> line by line, using the specified character
- * encoding and the specified line ending.
- * <p>
- * Character encoding names can be found at
- * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
- *
- * @param lines the lines to write, null entries produce blank lines
- * @param lineEnding the line separator to use, null is system default
- * @param output the <code>OutputStream</code> to write to, not null, not closed
- * @param encoding the encoding to use, null means platform default
- * @throws NullPointerException if the output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void writeLines(Collection lines, String lineEnding,
- OutputStream output, String encoding) throws IOException {
- if (encoding == null) {
- writeLines(lines, lineEnding, output);
- } else {
- if (lines == null) {
- return;
- }
- if (lineEnding == null) {
- lineEnding = LINE_SEPARATOR;
- }
- for (Iterator it = lines.iterator(); it.hasNext(); ) {
- Object line = it.next();
- if (line != null) {
- output.write(line.toString().getBytes(encoding));
- }
- output.write(lineEnding.getBytes(encoding));
- }
- }
- }
-
- /**
- * Writes the <code>toString()</code> value of each item in a collection to
- * a <code>Writer</code> line by line, using the specified line ending.
- *
- * @param lines the lines to write, null entries produce blank lines
- * @param lineEnding the line separator to use, null is system default
- * @param writer the <code>Writer</code> to write to, not null, not closed
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void writeLines(Collection lines, String lineEnding,
- Writer writer) throws IOException {
- if (lines == null) {
- return;
- }
- if (lineEnding == null) {
- lineEnding = LINE_SEPARATOR;
- }
- for (Iterator it = lines.iterator(); it.hasNext(); ) {
- Object line = it.next();
- if (line != null) {
- writer.write(line.toString());
- }
- writer.write(lineEnding);
- }
- }
-
- // copy from InputStream
- //-----------------------------------------------------------------------
- /**
- * Copy bytes from an <code>InputStream</code> to an
- * <code>OutputStream</code>.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedInputStream</code>.
- * <p>
- * Large streams (over 2GB) will return a bytes copied value of
- * <code>-1</code> after the copy has completed since the correct
- * number of bytes cannot be returned as an int. For large streams
- * use the <code>copyLarge(InputStream, OutputStream)</code> method.
- *
- * @param input the <code>InputStream</code> to read from
- * @param output the <code>OutputStream</code> to write to
- * @return the number of bytes copied
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
- * @throws ArithmeticException if the byte count is too large
- * @since Commons IO 1.1
- */
- public static int copy(InputStream input, OutputStream output) throws IOException {
- long count = copyLarge(input, output);
- if (count > Integer.MAX_VALUE) {
- return -1;
- }
- return (int) count;
- }
-
- /**
- * Copy bytes from a large (over 2GB) <code>InputStream</code> to an
- * <code>OutputStream</code>.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedInputStream</code>.
- *
- * @param input the <code>InputStream</code> to read from
- * @param output the <code>OutputStream</code> to write to
- * @return the number of bytes copied
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.3
- */
- public static long copyLarge(InputStream input, OutputStream output)
- throws IOException {
- byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
- long count = 0;
- int n = 0;
- while (-1 != (n = input.read(buffer))) {
- output.write(buffer, 0, n);
- count += n;
- }
- return count;
- }
-
- /**
- * Copy bytes from an <code>InputStream</code> to chars on a
- * <code>Writer</code> using the default character encoding of the platform.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedInputStream</code>.
- * <p>
- * This method uses {@link InputStreamReader}.
- *
- * @param input the <code>InputStream</code> to read from
- * @param output the <code>Writer</code> to write to
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void copy(InputStream input, Writer output)
- throws IOException {
- InputStreamReader in = new InputStreamReader(input);
- copy(in, output);
- }
-
- /**
- * Copy bytes from an <code>InputStream</code> to chars on a
- * <code>Writer</code> using the specified character encoding.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedInputStream</code>.
- * <p>
- * Character encoding names can be found at
- * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
- * <p>
- * This method uses {@link InputStreamReader}.
- *
- * @param input the <code>InputStream</code> to read from
- * @param output the <code>Writer</code> to write to
- * @param encoding the encoding to use, null means platform default
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void copy(InputStream input, Writer output, String encoding)
- throws IOException {
- if (encoding == null) {
- copy(input, output);
- } else {
- InputStreamReader in = new InputStreamReader(input, encoding);
- copy(in, output);
- }
- }
-
- // copy from Reader
- //-----------------------------------------------------------------------
- /**
- * Copy chars from a <code>Reader</code> to a <code>Writer</code>.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedReader</code>.
- * <p>
- * Large streams (over 2GB) will return a chars copied value of
- * <code>-1</code> after the copy has completed since the correct
- * number of chars cannot be returned as an int. For large streams
- * use the <code>copyLarge(Reader, Writer)</code> method.
- *
- * @param input the <code>Reader</code> to read from
- * @param output the <code>Writer</code> to write to
- * @return the number of characters copied
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
- * @throws ArithmeticException if the character count is too large
- * @since Commons IO 1.1
- */
- public static int copy(Reader input, Writer output) throws IOException {
- long count = copyLarge(input, output);
- if (count > Integer.MAX_VALUE) {
- return -1;
- }
- return (int) count;
- }
-
- /**
- * Copy chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedReader</code>.
- *
- * @param input the <code>Reader</code> to read from
- * @param output the <code>Writer</code> to write to
- * @return the number of characters copied
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.3
- */
- public static long copyLarge(Reader input, Writer output) throws IOException {
- char[] buffer = new char[DEFAULT_BUFFER_SIZE];
- long count = 0;
- int n = 0;
- while (-1 != (n = input.read(buffer))) {
- output.write(buffer, 0, n);
- count += n;
- }
- return count;
- }
-
- /**
- * Copy chars from a <code>Reader</code> to bytes on an
- * <code>OutputStream</code> using the default character encoding of the
- * platform, and calling flush.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedReader</code>.
- * <p>
- * Due to the implementation of OutputStreamWriter, this method performs a
- * flush.
- * <p>
- * This method uses {@link OutputStreamWriter}.
- *
- * @param input the <code>Reader</code> to read from
- * @param output the <code>OutputStream</code> to write to
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void copy(Reader input, OutputStream output)
- throws IOException {
- OutputStreamWriter out = new OutputStreamWriter(output);
- copy(input, out);
- // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
- // have to flush here.
- out.flush();
- }
-
- /**
- * Copy chars from a <code>Reader</code> to bytes on an
- * <code>OutputStream</code> using the specified character encoding, and
- * calling flush.
- * <p>
- * This method buffers the input internally, so there is no need to use a
- * <code>BufferedReader</code>.
- * <p>
- * Character encoding names can be found at
- * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
- * <p>
- * Due to the implementation of OutputStreamWriter, this method performs a
- * flush.
- * <p>
- * This method uses {@link OutputStreamWriter}.
- *
- * @param input the <code>Reader</code> to read from
- * @param output the <code>OutputStream</code> to write to
- * @param encoding the encoding to use, null means platform default
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static void copy(Reader input, OutputStream output, String encoding)
- throws IOException {
- if (encoding == null) {
- copy(input, output);
- } else {
- OutputStreamWriter out = new OutputStreamWriter(output, encoding);
- copy(input, out);
- // XXX Unless anyone is planning on rewriting OutputStreamWriter,
- // we have to flush here.
- out.flush();
- }
- }
-
- // content equals
- //-----------------------------------------------------------------------
- /**
- * Compare the contents of two Streams to determine if they are equal or
- * not.
- * <p>
- * This method buffers the input internally using
- * <code>BufferedInputStream</code> if they are not already buffered.
- *
- * @param input1 the first stream
- * @param input2 the second stream
- * @return true if the content of the streams are equal or they both don't
- * exist, false otherwise
- * @throws NullPointerException if either input is null
- * @throws IOException if an I/O error occurs
- */
- public static boolean contentEquals(InputStream input1, InputStream input2)
- throws IOException {
- if (!(input1 instanceof BufferedInputStream)) {
- input1 = new BufferedInputStream(input1);
- }
- if (!(input2 instanceof BufferedInputStream)) {
- input2 = new BufferedInputStream(input2);
- }
-
- int ch = input1.read();
- while (-1 != ch) {
- int ch2 = input2.read();
- if (ch != ch2) {
- return false;
- }
- ch = input1.read();
- }
-
- int ch2 = input2.read();
- return (ch2 == -1);
- }
-
- /**
- * Compare the contents of two Readers to determine if they are equal or
- * not.
- * <p>
- * This method buffers the input internally using
- * <code>BufferedReader</code> if they are not already buffered.
- *
- * @param input1 the first reader
- * @param input2 the second reader
- * @return true if the content of the readers are equal or they both don't
- * exist, false otherwise
- * @throws NullPointerException if either input is null
- * @throws IOException if an I/O error occurs
- * @since Commons IO 1.1
- */
- public static boolean contentEquals(Reader input1, Reader input2)
- throws IOException {
- if (!(input1 instanceof BufferedReader)) {
- input1 = new BufferedReader(input1);
- }
- if (!(input2 instanceof BufferedReader)) {
- input2 = new BufferedReader(input2);
- }
-
- int ch = input1.read();
- while (-1 != ch) {
- int ch2 = input2.read();
- if (ch != ch2) {
- return false;
- }
- ch = input1.read();
- }
-
- int ch2 = input2.read();
- return (ch2 == -1);
- }
-
-}
diff --git a/src/org/apache/commons/io/LineIterator.java b/src/org/apache/commons/io/LineIterator.java
deleted file mode 100644
index eac47d23a..000000000
--- a/src/org/apache/commons/io/LineIterator.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-/**
- * An Iterator over the lines in a <code>Reader</code>.
- * <p>
- * <code>LineIterator</code> holds a reference to an open <code>Reader</code>.
- * When you have finished with the iterator you should close the reader
- * to free internal resources. This can be done by closing the reader directly,
- * or by calling the {@link #close()} or {@link #closeQuietly(LineIterator)}
- * method on the iterator.
- * <p>
- * The recommended usage pattern is:
- * <pre>
- * LineIterator it = FileUtils.lineIterator(file, "UTF-8");
- * try {
- * while (it.hasNext()) {
- * String line = it.nextLine();
- * /// do something with line
- * }
- * } finally {
- * LineIterator.closeQuietly(iterator);
- * }
- * </pre>
- *
- * @author Niall Pemberton
- * @author Stephen Colebourne
- * @author Sandy McArthur
- * @version $Id: LineIterator.java 437567 2006-08-28 06:39:07Z bayard $
- * @since Commons IO 1.2
- */
-public class LineIterator implements Iterator {
-
- /** The reader that is being read. */
- private final BufferedReader bufferedReader;
- /** The current line. */
- private String cachedLine;
- /** A flag indicating if the iterator has been fully read. */
- private boolean finished = false;
-
- /**
- * Constructs an iterator of the lines for a <code>Reader</code>.
- *
- * @param reader the <code>Reader</code> to read from, not null
- * @throws IllegalArgumentException if the reader is null
- */
- public LineIterator(final Reader reader) throws IllegalArgumentException {
- if (reader == null) {
- throw new IllegalArgumentException("Reader must not be null");
- }
- if (reader instanceof BufferedReader) {
- bufferedReader = (BufferedReader) reader;
- } else {
- bufferedReader = new BufferedReader(reader);
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Indicates whether the <code>Reader</code> has more lines.
- * If there is an <code>IOException</code> then {@link #close()} will
- * be called on this instance.
- *
- * @return <code>true</code> if the Reader has more lines
- * @throws IllegalStateException if an IO exception occurs
- */
- public boolean hasNext() {
- if (cachedLine != null) {
- return true;
- } else if (finished) {
- return false;
- } else {
- try {
- while (true) {
- String line = bufferedReader.readLine();
- if (line == null) {
- finished = true;
- return false;
- } else if (isValidLine(line)) {
- cachedLine = line;
- return true;
- }
- }
- } catch(IOException ioe) {
- close();
- throw new IllegalStateException(ioe.toString());
- }
- }
- }
-
- /**
- * Overridable method to validate each line that is returned.
- *
- * @param line the line that is to be validated
- * @return true if valid, false to remove from the iterator
- */
- protected boolean isValidLine(String line) {
- return true;
- }
-
- /**
- * Returns the next line in the wrapped <code>Reader</code>.
- *
- * @return the next line from the input
- * @throws NoSuchElementException if there is no line to return
- */
- public Object next() {
- return nextLine();
- }
-
- /**
- * Returns the next line in the wrapped <code>Reader</code>.
- *
- * @return the next line from the input
- * @throws NoSuchElementException if there is no line to return
- */
- public String nextLine() {
- if (!hasNext()) {
- throw new NoSuchElementException("No more lines");
- }
- String currentLine = cachedLine;
- cachedLine = null;
- return currentLine;
- }
-
- /**
- * Closes the underlying <code>Reader</code> quietly.
- * This method is useful if you only want to process the first few
- * lines of a larger file. If you do not close the iterator
- * then the <code>Reader</code> remains open.
- * This method can safely be called multiple times.
- */
- public void close() {
- finished = true;
- IOUtils.closeQuietly(bufferedReader);
- cachedLine = null;
- }
-
- /**
- * Unsupported.
- *
- * @throws UnsupportedOperationException always
- */
- public void remove() {
- throw new UnsupportedOperationException("Remove unsupported on LineIterator");
- }
-
- //-----------------------------------------------------------------------
- /**
- * Closes the iterator, handling null and ignoring exceptions.
- *
- * @param iterator the iterator to close
- */
- public static void closeQuietly(LineIterator iterator) {
- if (iterator != null) {
- iterator.close();
- }
- }
-
-}
diff --git a/src/org/apache/commons/io/comparator/DefaultFileComparator.java b/src/org/apache/commons/io/comparator/DefaultFileComparator.java
deleted file mode 100644
index d36076288..000000000
--- a/src/org/apache/commons/io/comparator/DefaultFileComparator.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.comparator;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.Comparator;
-
-/**
- * Compare two files using the <b>default</b> {@link File#compareTo(File)} method.
- * <p>
- * This comparator can be used to sort lists or arrays of files
- * by using the default file comparison.
- * <p>
- * Example of sorting a list of files using the
- * {@link #DEFAULT_COMPARATOR} singleton instance:
- * <pre>
- * List&lt;File&gt; list = ...
- * Collections.sort(list, DefaultFileComparator.DEFAULT_COMPARATOR);
- * </pre>
- * <p>
- * Example of doing a <i>reverse</i> sort of an array of files using the
- * {@link #DEFAULT_REVERSE} singleton instance:
- * <pre>
- * File[] array = ...
- * Arrays.sort(array, DefaultFileComparator.DEFAULT_REVERSE);
- * </pre>
- * <p>
- *
- * @version $Revision: 609243 $ $Date: 2008-01-06 00:30:42 +0000 (Sun, 06 Jan 2008) $
- * @since Commons IO 1.4
- */
-public class DefaultFileComparator implements Comparator, Serializable {
-
- /** Singleton default comparator instance */
- public static final Comparator DEFAULT_COMPARATOR = new DefaultFileComparator();
-
- /** Singleton reverse default comparator instance */
- public static final Comparator DEFAULT_REVERSE = new ReverseComparator(DEFAULT_COMPARATOR);
-
- /**
- * Compare the two files using the {@link File#compareTo(File)} method.
- *
- * @param obj1 The first file to compare
- * @param obj2 The second file to compare
- * @return the result of calling file1's
- * {@link File#compareTo(File)} with file2 as the parameter.
- */
- public int compare(Object obj1, Object obj2) {
- File file1 = (File)obj1;
- File file2 = (File)obj2;
- return file1.compareTo(file2);
- }
-}
diff --git a/src/org/apache/commons/io/comparator/ExtensionFileComparator.java b/src/org/apache/commons/io/comparator/ExtensionFileComparator.java
deleted file mode 100644
index 158480fb3..000000000
--- a/src/org/apache/commons/io/comparator/ExtensionFileComparator.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.comparator;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.Comparator;
-
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.io.IOCase;
-
-/**
- * Compare the file name <b>extensions</b> for order
- * (see {@link FilenameUtils#getExtension(String)}).
- * <p>
- * This comparator can be used to sort lists or arrays of files
- * by their file extension either in a case-sensitive, case-insensitive or
- * system dependant case sensitive way. A number of singleton instances
- * are provided for the various case sensitivity options (using {@link IOCase})
- * and the reverse of those options.
- * <p>
- * Example of a <i>case-sensitive</i> file extension sort using the
- * {@link #EXTENSION_COMPARATOR} singleton instance:
- * <pre>
- * List&lt;File&gt; list = ...
- * Collections.sort(list, ExtensionFileComparator.EXTENSION_COMPARATOR);
- * </pre>
- * <p>
- * Example of a <i>reverse case-insensitive</i> file extension sort using the
- * {@link #EXTENSION_INSENSITIVE_REVERSE} singleton instance:
- * <pre>
- * File[] array = ...
- * Arrays.sort(array, ExtensionFileComparator.EXTENSION_INSENSITIVE_REVERSE);
- * </pre>
- * <p>
- *
- * @version $Revision: 609243 $ $Date: 2008-01-06 00:30:42 +0000 (Sun, 06 Jan 2008) $
- * @since Commons IO 1.4
- */
-public class ExtensionFileComparator implements Comparator, Serializable {
-
- /** Case-sensitive extension comparator instance (see {@link IOCase#SENSITIVE}) */
- public static final Comparator EXTENSION_COMPARATOR = new ExtensionFileComparator();
-
- /** Reverse case-sensitive extension comparator instance (see {@link IOCase#SENSITIVE}) */
- public static final Comparator EXTENSION_REVERSE = new ReverseComparator(EXTENSION_COMPARATOR);
-
- /** Case-insensitive extension comparator instance (see {@link IOCase#INSENSITIVE}) */
- public static final Comparator EXTENSION_INSENSITIVE_COMPARATOR = new ExtensionFileComparator(IOCase.INSENSITIVE);
-
- /** Reverse case-insensitive extension comparator instance (see {@link IOCase#INSENSITIVE}) */
- public static final Comparator EXTENSION_INSENSITIVE_REVERSE
- = new ReverseComparator(EXTENSION_INSENSITIVE_COMPARATOR);
-
- /** System sensitive extension comparator instance (see {@link IOCase#SYSTEM}) */
- public static final Comparator EXTENSION_SYSTEM_COMPARATOR = new ExtensionFileComparator(IOCase.SYSTEM);
-
- /** Reverse system sensitive path comparator instance (see {@link IOCase#SYSTEM}) */
- public static final Comparator EXTENSION_SYSTEM_REVERSE = new ReverseComparator(EXTENSION_SYSTEM_COMPARATOR);
-
- /** Whether the comparison is case sensitive. */
- private final IOCase caseSensitivity;
-
- /**
- * Construct a case sensitive file extension comparator instance.
- */
- public ExtensionFileComparator() {
- this.caseSensitivity = IOCase.SENSITIVE;
- }
-
- /**
- * Construct a file extension comparator instance with the specified case-sensitivity.
- *
- * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
- */
- public ExtensionFileComparator(IOCase caseSensitivity) {
- this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity;
- }
-
- /**
- * Compare the extensions of two files the specified case sensitivity.
- *
- * @param obj1 The first file to compare
- * @param obj2 The second file to compare
- * @return a negative value if the first file's extension
- * is less than the second, zero if the extensions are the
- * same and a positive value if the first files extension
- * is greater than the second file.
- *
- */
- public int compare(Object obj1, Object obj2) {
- File file1 = (File)obj1;
- File file2 = (File)obj2;
- String suffix1 = FilenameUtils.getExtension(file1.getName());
- String suffix2 = FilenameUtils.getExtension(file2.getName());
- return caseSensitivity.checkCompareTo(suffix1, suffix2);
- }
-}
diff --git a/src/org/apache/commons/io/comparator/LastModifiedFileComparator.java b/src/org/apache/commons/io/comparator/LastModifiedFileComparator.java
deleted file mode 100644
index 8265023d0..000000000
--- a/src/org/apache/commons/io/comparator/LastModifiedFileComparator.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.comparator;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.Comparator;
-
-/**
- * Compare the <b>last modified date/time</b> of two files for order
- * (see {@link File#lastModified()}).
- * <p>
- * This comparator can be used to sort lists or arrays of files
- * by their last modified date/time.
- * <p>
- * Example of sorting a list of files using the
- * {@link #LASTMODIFIED_COMPARATOR} singleton instance:
- * <pre>
- * List&lt;File&gt; list = ...
- * Collections.sort(list, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR);
- * </pre>
- * <p>
- * Example of doing a <i>reverse</i> sort of an array of files using the
- * {@link #LASTMODIFIED_REVERSE} singleton instance:
- * <pre>
- * File[] array = ...
- * Arrays.sort(array, LastModifiedFileComparator.LASTMODIFIED_REVERSE);
- * </pre>
- * <p>
- *
- * @version $Revision: 609243 $ $Date: 2008-01-06 00:30:42 +0000 (Sun, 06 Jan 2008) $
- * @since Commons IO 1.4
- */
-public class LastModifiedFileComparator implements Comparator, Serializable {
-
- /** Last modified comparator instance */
- public static final Comparator LASTMODIFIED_COMPARATOR = new LastModifiedFileComparator();
-
- /** Reverse last modified comparator instance */
- public static final Comparator LASTMODIFIED_REVERSE = new ReverseComparator(LASTMODIFIED_COMPARATOR);
-
- /**
- * Compare the last the last modified date/time of two files.
- *
- * @param obj1 The first file to compare
- * @param obj2 The second file to compare
- * @return a negative value if the first file's lastmodified date/time
- * is less than the second, zero if the lastmodified date/time are the
- * same and a positive value if the first files lastmodified date/time
- * is greater than the second file.
- *
- */
- public int compare(Object obj1, Object obj2) {
- File file1 = (File)obj1;
- File file2 = (File)obj2;
- long result = file1.lastModified() - file2.lastModified();
- if (result < 0) {
- return -1;
- } else if (result > 0) {
- return 1;
- } else {
- return 0;
- }
- }
-}
diff --git a/src/org/apache/commons/io/comparator/NameFileComparator.java b/src/org/apache/commons/io/comparator/NameFileComparator.java
deleted file mode 100644
index 76af21eeb..000000000
--- a/src/org/apache/commons/io/comparator/NameFileComparator.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.comparator;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.Comparator;
-
-import org.apache.commons.io.IOCase;
-
-/**
- * Compare the <b>names</b> of two files for order (see {@link File#getName()}).
- * <p>
- * This comparator can be used to sort lists or arrays of files
- * by their name either in a case-sensitive, case-insensitive or
- * system dependant case sensitive way. A number of singleton instances
- * are provided for the various case sensitivity options (using {@link IOCase})
- * and the reverse of those options.
- * <p>
- * Example of a <i>case-sensitive</i> file name sort using the
- * {@link #NAME_COMPARATOR} singleton instance:
- * <pre>
- * List&lt;File&gt; list = ...
- * Collections.sort(list, NameFileComparator.NAME_COMPARATOR);
- * </pre>
- * <p>
- * Example of a <i>reverse case-insensitive</i> file name sort using the
- * {@link #NAME_INSENSITIVE_REVERSE} singleton instance:
- * <pre>
- * File[] array = ...
- * Arrays.sort(array, NameFileComparator.NAME_INSENSITIVE_REVERSE);
- * </pre>
- * <p>
- *
- * @version $Revision: 609243 $ $Date: 2008-01-06 00:30:42 +0000 (Sun, 06 Jan 2008) $
- * @since Commons IO 1.4
- */
-public class NameFileComparator implements Comparator, Serializable {
-
- /** Case-sensitive name comparator instance (see {@link IOCase#SENSITIVE}) */
- public static final Comparator NAME_COMPARATOR = new NameFileComparator();
-
- /** Reverse case-sensitive name comparator instance (see {@link IOCase#SENSITIVE}) */
- public static final Comparator NAME_REVERSE = new ReverseComparator(NAME_COMPARATOR);
-
- /** Case-insensitive name comparator instance (see {@link IOCase#INSENSITIVE}) */
- public static final Comparator NAME_INSENSITIVE_COMPARATOR = new NameFileComparator(IOCase.INSENSITIVE);
-
- /** Reverse case-insensitive name comparator instance (see {@link IOCase#INSENSITIVE}) */
- public static final Comparator NAME_INSENSITIVE_REVERSE = new ReverseComparator(NAME_INSENSITIVE_COMPARATOR);
-
- /** System sensitive name comparator instance (see {@link IOCase#SYSTEM}) */
- public static final Comparator NAME_SYSTEM_COMPARATOR = new NameFileComparator(IOCase.SYSTEM);
-
- /** Reverse system sensitive name comparator instance (see {@link IOCase#SYSTEM}) */
- public static final Comparator NAME_SYSTEM_REVERSE = new ReverseComparator(NAME_SYSTEM_COMPARATOR);
-
- /** Whether the comparison is case sensitive. */
- private final IOCase caseSensitivity;
-
- /**
- * Construct a case sensitive file name comparator instance.
- */
- public NameFileComparator() {
- this.caseSensitivity = IOCase.SENSITIVE;
- }
-
- /**
- * Construct a file name comparator instance with the specified case-sensitivity.
- *
- * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
- */
- public NameFileComparator(IOCase caseSensitivity) {
- this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity;
- }
-
- /**
- * Compare the names of two files with the specified case sensitivity.
- *
- * @param obj1 The first file to compare
- * @param obj2 The second file to compare
- * @return a negative value if the first file's name
- * is less than the second, zero if the names are the
- * same and a positive value if the first files name
- * is greater than the second file.
- */
- public int compare(Object obj1, Object obj2) {
- File file1 = (File)obj1;
- File file2 = (File)obj2;
- return caseSensitivity.checkCompareTo(file1.getName(), file2.getName());
- }
-}
diff --git a/src/org/apache/commons/io/comparator/PathFileComparator.java b/src/org/apache/commons/io/comparator/PathFileComparator.java
deleted file mode 100644
index 0b28b6960..000000000
--- a/src/org/apache/commons/io/comparator/PathFileComparator.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.comparator;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.Comparator;
-
-import org.apache.commons.io.IOCase;
-
-/**
- * Compare the <b>path</b> of two files for order (see {@link File#getPath()}).
- * <p>
- * This comparator can be used to sort lists or arrays of files
- * by their path either in a case-sensitive, case-insensitive or
- * system dependant case sensitive way. A number of singleton instances
- * are provided for the various case sensitivity options (using {@link IOCase})
- * and the reverse of those options.
- * <p>
- * Example of a <i>case-sensitive</i> file path sort using the
- * {@link #PATH_COMPARATOR} singleton instance:
- * <pre>
- * List&lt;File&gt; list = ...
- * Collections.sort(list, PathFileComparator.PATH_COMPARATOR);
- * </pre>
- * <p>
- * Example of a <i>reverse case-insensitive</i> file path sort using the
- * {@link #PATH_INSENSITIVE_REVERSE} singleton instance:
- * <pre>
- * File[] array = ...
- * Arrays.sort(array, PathFileComparator.PATH_INSENSITIVE_REVERSE);
- * </pre>
- * <p>
- *
- * @version $Revision: 609243 $ $Date: 2008-01-06 00:30:42 +0000 (Sun, 06 Jan 2008) $
- * @since Commons IO 1.4
- */
-public class PathFileComparator implements Comparator, Serializable {
-
- /** Case-sensitive path comparator instance (see {@link IOCase#SENSITIVE}) */
- public static final Comparator PATH_COMPARATOR = new PathFileComparator();
-
- /** Reverse case-sensitive path comparator instance (see {@link IOCase#SENSITIVE}) */
- public static final Comparator PATH_REVERSE = new ReverseComparator(PATH_COMPARATOR);
-
- /** Case-insensitive path comparator instance (see {@link IOCase#INSENSITIVE}) */
- public static final Comparator PATH_INSENSITIVE_COMPARATOR = new PathFileComparator(IOCase.INSENSITIVE);
-
- /** Reverse case-insensitive path comparator instance (see {@link IOCase#INSENSITIVE}) */
- public static final Comparator PATH_INSENSITIVE_REVERSE = new ReverseComparator(PATH_INSENSITIVE_COMPARATOR);
-
- /** System sensitive path comparator instance (see {@link IOCase#SYSTEM}) */
- public static final Comparator PATH_SYSTEM_COMPARATOR = new PathFileComparator(IOCase.SYSTEM);
-
- /** Reverse system sensitive path comparator instance (see {@link IOCase#SYSTEM}) */
- public static final Comparator PATH_SYSTEM_REVERSE = new ReverseComparator(PATH_SYSTEM_COMPARATOR);
-
- /** Whether the comparison is case sensitive. */
- private final IOCase caseSensitivity;
-
- /**
- * Construct a case sensitive file path comparator instance.
- */
- public PathFileComparator() {
- this.caseSensitivity = IOCase.SENSITIVE;
- }
-
- /**
- * Construct a file path comparator instance with the specified case-sensitivity.
- *
- * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
- */
- public PathFileComparator(IOCase caseSensitivity) {
- this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity;
- }
-
- /**
- * Compare the paths of two files the specified case sensitivity.
- *
- * @param obj1 The first file to compare
- * @param obj2 The second file to compare
- * @return a negative value if the first file's path
- * is less than the second, zero if the paths are the
- * same and a positive value if the first files path
- * is greater than the second file.
- *
- */
- public int compare(Object obj1, Object obj2) {
- File file1 = (File)obj1;
- File file2 = (File)obj2;
- return caseSensitivity.checkCompareTo(file1.getPath(), file2.getPath());
- }
-}
diff --git a/src/org/apache/commons/io/comparator/ReverseComparator.java b/src/org/apache/commons/io/comparator/ReverseComparator.java
deleted file mode 100644
index af9749ee3..000000000
--- a/src/org/apache/commons/io/comparator/ReverseComparator.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.comparator;
-
-import java.io.Serializable;
-import java.util.Comparator;
-
-/**
- * Reverses the result of comparing two objects using
- * the delegate {@link Comparator}.
- *
- * @version $Revision: 609243 $ $Date: 2008-01-06 00:30:42 +0000 (Sun, 06 Jan 2008) $
- * @since Commons IO 1.4
- */
-class ReverseComparator implements Comparator, Serializable {
-
- private final Comparator delegate;
-
- /**
- * Construct an instance with the sepecified delegate {@link Comparator}.
- *
- * @param delegate The comparator to delegate to
- */
- public ReverseComparator(Comparator delegate) {
- if (delegate == null) {
- throw new IllegalArgumentException("Delegate comparator is missing");
- }
- this.delegate = delegate;
- }
-
- /**
- * Compare using the delegate Comparator, but reversing the result.
- *
- * @param obj1 The first object to compare
- * @param obj2 The second object to compare
- * @return the result from the delegate {@link Comparator#compare(Object, Object)}
- * reversing the value (i.e. positive becomes negative and vice versa)
- */
- public int compare(Object obj1, Object obj2) {
- return delegate.compare(obj2, obj1); // parameters switched round
- }
-
-}
diff --git a/src/org/apache/commons/io/comparator/SizeFileComparator.java b/src/org/apache/commons/io/comparator/SizeFileComparator.java
deleted file mode 100644
index a1621671c..000000000
--- a/src/org/apache/commons/io/comparator/SizeFileComparator.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.comparator;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.Comparator;
-
-import org.apache.commons.io.FileUtils;
-
-/**
- * Compare the <b>length/size</b> of two files for order (see
- * {@link File#length()} and {@link FileUtils#sizeOfDirectory(File)}).
- * <p>
- * This comparator can be used to sort lists or arrays of files
- * by their length/size.
- * <p>
- * Example of sorting a list of files using the
- * {@link #SIZE_COMPARATOR} singleton instance:
- * <pre>
- * List&lt;File&gt; list = ...
- * Collections.sort(list, LengthFileComparator.LENGTH_COMPARATOR);
- * </pre>
- * <p>
- * Example of doing a <i>reverse</i> sort of an array of files using the
- * {@link #SIZE_REVERSE} singleton instance:
- * <pre>
- * File[] array = ...
- * Arrays.sort(array, LengthFileComparator.LENGTH_REVERSE);
- * </pre>
- * <p>
- * <strong>N.B.</strong> Directories are treated as <b>zero size</b> unless
- * <code>sumDirectoryContents</code> is <code>true</code>.
- *
- * @version $Revision: 609243 $ $Date: 2008-01-06 00:30:42 +0000 (Sun, 06 Jan 2008) $
- * @since Commons IO 1.4
- */
-public class SizeFileComparator implements Comparator, Serializable {
-
- /** Size comparator instance - directories are treated as zero size */
- public static final Comparator SIZE_COMPARATOR = new SizeFileComparator();
-
- /** Reverse size comparator instance - directories are treated as zero size */
- public static final Comparator SIZE_REVERSE = new ReverseComparator(SIZE_COMPARATOR);
-
- /**
- * Size comparator instance which sums the size of a directory's contents
- * using {@link FileUtils#sizeOfDirectory(File)}
- */
- public static final Comparator SIZE_SUMDIR_COMPARATOR = new SizeFileComparator(true);
-
- /**
- * Reverse size comparator instance which sums the size of a directory's contents
- * using {@link FileUtils#sizeOfDirectory(File)}
- */
- public static final Comparator SIZE_SUMDIR_REVERSE = new ReverseComparator(SIZE_SUMDIR_COMPARATOR);
-
- /** Whether the sum of the directory's contents should be calculated. */
- private final boolean sumDirectoryContents;
-
- /**
- * Construct a file size comparator instance (directories treated as zero size).
- */
- public SizeFileComparator() {
- this.sumDirectoryContents = false;
- }
-
- /**
- * Construct a file size comparator instance specifying whether the size of
- * the directory contents should be aggregated.
- * <p>
- * If the <code>sumDirectoryContents</code> is <code>true</code> The size of
- * directories is calculated using {@link FileUtils#sizeOfDirectory(File)}.
- *
- * @param sumDirectoryContents <code>true</code> if the sum of the directoryies contents
- * should be calculated, otherwise <code>false</code> if directories should be treated
- * as size zero (see {@link FileUtils#sizeOfDirectory(File)}).
- */
- public SizeFileComparator(boolean sumDirectoryContents) {
- this.sumDirectoryContents = sumDirectoryContents;
- }
-
- /**
- * Compare the length of two files.
- *
- * @param obj1 The first file to compare
- * @param obj2 The second file to compare
- * @return a negative value if the first file's length
- * is less than the second, zero if the lengths are the
- * same and a positive value if the first files length
- * is greater than the second file.
- *
- */
- public int compare(Object obj1, Object obj2) {
- File file1 = (File)obj1;
- File file2 = (File)obj2;
- long size1 = 0;
- if (file1.isDirectory()) {
- size1 = sumDirectoryContents && file1.exists() ? FileUtils.sizeOfDirectory(file1) : 0;
- } else {
- size1 = file1.length();
- }
- long size2 = 0;
- if (file2.isDirectory()) {
- size2 = sumDirectoryContents && file2.exists() ? FileUtils.sizeOfDirectory(file2) : 0;
- } else {
- size2 = file2.length();
- }
- long result = size1 - size2;
- if (result < 0) {
- return -1;
- } else if (result > 0) {
- return 1;
- } else {
- return 0;
- }
- }
-}
diff --git a/src/org/apache/commons/io/comparator/package.html b/src/org/apache/commons/io/comparator/package.html
deleted file mode 100644
index a2f756f18..000000000
--- a/src/org/apache/commons/io/comparator/package.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<html>
-<body>
-<p>This package provides various {@link java.util.Comparator} implementations
-for {@link java.io.File}s.
-</p>
-
-</body>
-</html>
diff --git a/src/org/apache/commons/io/filefilter/AbstractFileFilter.java b/src/org/apache/commons/io/filefilter/AbstractFileFilter.java
deleted file mode 100644
index 9e188f82e..000000000
--- a/src/org/apache/commons/io/filefilter/AbstractFileFilter.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-
-/**
- * An abstract class which implements the Java FileFilter and FilenameFilter
- * interfaces via the IOFileFilter interface.
- * <p>
- * Note that a subclass <b>must</b> override one of the accept methods,
- * otherwise your class will infinitely loop.
- *
- * @since Commons IO 1.0
- * @version $Revision: 539231 $ $Date: 2007-05-18 04:10:33 +0100 (Fri, 18 May 2007) $
- *
- * @author Stephen Colebourne
- */
-public abstract class AbstractFileFilter implements IOFileFilter {
-
- /**
- * Checks to see if the File should be accepted by this filter.
- *
- * @param file the File to check
- * @return true if this file matches the test
- */
- public boolean accept(File file) {
- return accept(file.getParentFile(), file.getName());
- }
-
- /**
- * Checks to see if the File should be accepted by this filter.
- *
- * @param dir the directory File to check
- * @param name the filename within the directory to check
- * @return true if this file matches the test
- */
- public boolean accept(File dir, String name) {
- return accept(new File(dir, name));
- }
-
- /**
- * Provide a String representaion of this file filter.
- *
- * @return a String representaion
- */
- public String toString() {
- String name = getClass().getName();
- int period = name.lastIndexOf('.');
- return (period > 0 ? name.substring(period + 1) : name);
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/AgeFileFilter.java b/src/org/apache/commons/io/filefilter/AgeFileFilter.java
deleted file mode 100644
index ab73cb840..000000000
--- a/src/org/apache/commons/io/filefilter/AgeFileFilter.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.Date;
-
-import org.apache.commons.io.FileUtils;
-
-/**
- * Filters files based on a cutoff time, can filter either newer
- * files or files equal to or older.
- * <p>
- * For example, to print all files and directories in the
- * current directory older than one day:
- *
- * <pre>
- * File dir = new File(".");
- * // We are interested in files older than one day
- * long cutoff = System.currentTimeMillis() - (24 * 60 * 60 * 1000);
- * String[] files = dir.list( new AgeFileFilter(cutoff) );
- * for ( int i = 0; i &lt; files.length; i++ ) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * @author Rahul Akolkar
- * @version $Id: AgeFileFilter.java 606381 2007-12-22 02:03:16Z ggregory $
- * @since Commons IO 1.2
- */
-public class AgeFileFilter extends AbstractFileFilter implements Serializable {
-
- /** The cutoff time threshold. */
- private final long cutoff;
- /** Whether the files accepted will be older or newer. */
- private final boolean acceptOlder;
-
- /**
- * Constructs a new age file filter for files equal to or older than
- * a certain cutoff
- *
- * @param cutoff the threshold age of the files
- */
- public AgeFileFilter(long cutoff) {
- this(cutoff, true);
- }
-
- /**
- * Constructs a new age file filter for files on any one side
- * of a certain cutoff.
- *
- * @param cutoff the threshold age of the files
- * @param acceptOlder if true, older files (at or before the cutoff)
- * are accepted, else newer ones (after the cutoff).
- */
- public AgeFileFilter(long cutoff, boolean acceptOlder) {
- this.acceptOlder = acceptOlder;
- this.cutoff = cutoff;
- }
-
- /**
- * Constructs a new age file filter for files older than (at or before)
- * a certain cutoff date.
- *
- * @param cutoffDate the threshold age of the files
- */
- public AgeFileFilter(Date cutoffDate) {
- this(cutoffDate, true);
- }
-
- /**
- * Constructs a new age file filter for files on any one side
- * of a certain cutoff date.
- *
- * @param cutoffDate the threshold age of the files
- * @param acceptOlder if true, older files (at or before the cutoff)
- * are accepted, else newer ones (after the cutoff).
- */
- public AgeFileFilter(Date cutoffDate, boolean acceptOlder) {
- this(cutoffDate.getTime(), acceptOlder);
- }
-
- /**
- * Constructs a new age file filter for files older than (at or before)
- * a certain File (whose last modification time will be used as reference).
- *
- * @param cutoffReference the file whose last modification
- * time is usesd as the threshold age of the files
- */
- public AgeFileFilter(File cutoffReference) {
- this(cutoffReference, true);
- }
-
- /**
- * Constructs a new age file filter for files on any one side
- * of a certain File (whose last modification time will be used as
- * reference).
- *
- * @param cutoffReference the file whose last modification
- * time is usesd as the threshold age of the files
- * @param acceptOlder if true, older files (at or before the cutoff)
- * are accepted, else newer ones (after the cutoff).
- */
- public AgeFileFilter(File cutoffReference, boolean acceptOlder) {
- this(cutoffReference.lastModified(), acceptOlder);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Checks to see if the last modification of the file matches cutoff
- * favorably.
- * <p>
- * If last modification time equals cutoff and newer files are required,
- * file <b>IS NOT</b> selected.
- * If last modification time equals cutoff and older files are required,
- * file <b>IS</b> selected.
- *
- * @param file the File to check
- * @return true if the filename matches
- */
- public boolean accept(File file) {
- boolean newer = FileUtils.isFileNewer(file, cutoff);
- return acceptOlder ? !newer : newer;
- }
-
- /**
- * Provide a String representaion of this file filter.
- *
- * @return a String representaion
- */
- public String toString() {
- String condition = acceptOlder ? "<=" : ">";
- return super.toString() + "(" + condition + cutoff + ")";
- }
-}
diff --git a/src/org/apache/commons/io/filefilter/AndFileFilter.java b/src/org/apache/commons/io/filefilter/AndFileFilter.java
deleted file mode 100644
index deda11f93..000000000
--- a/src/org/apache/commons/io/filefilter/AndFileFilter.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * A {@link java.io.FileFilter} providing conditional AND logic across a list of
- * file filters. This filter returns <code>true</code> if all filters in the
- * list return <code>true</code>. Otherwise, it returns <code>false</code>.
- * Checking of the file filter list stops when the first filter returns
- * <code>false</code>.
- *
- * @since Commons IO 1.0
- * @version $Revision: 606381 $ $Date: 2007-12-22 02:03:16 +0000 (Sat, 22 Dec 2007) $
- *
- * @author Steven Caswell
- */
-public class AndFileFilter
- extends AbstractFileFilter
- implements ConditionalFileFilter, Serializable {
-
- /** The list of file filters. */
- private List fileFilters;
-
- /**
- * Constructs a new instance of <code>AndFileFilter</code>.
- *
- * @since Commons IO 1.1
- */
- public AndFileFilter() {
- this.fileFilters = new ArrayList();
- }
-
- /**
- * Constructs a new instance of <code>AndFileFilter</code>
- * with the specified list of filters.
- *
- * @param fileFilters a List of IOFileFilter instances, copied, null ignored
- * @since Commons IO 1.1
- */
- public AndFileFilter(final List fileFilters) {
- if (fileFilters == null) {
- this.fileFilters = new ArrayList();
- } else {
- this.fileFilters = new ArrayList(fileFilters);
- }
- }
-
- /**
- * Constructs a new file filter that ANDs the result of two other filters.
- *
- * @param filter1 the first filter, must not be null
- * @param filter2 the second filter, must not be null
- * @throws IllegalArgumentException if either filter is null
- */
- public AndFileFilter(IOFileFilter filter1, IOFileFilter filter2) {
- if (filter1 == null || filter2 == null) {
- throw new IllegalArgumentException("The filters must not be null");
- }
- this.fileFilters = new ArrayList();
- addFileFilter(filter1);
- addFileFilter(filter2);
- }
-
- /**
- * {@inheritDoc}
- */
- public void addFileFilter(final IOFileFilter ioFileFilter) {
- this.fileFilters.add(ioFileFilter);
- }
-
- /**
- * {@inheritDoc}
- */
- public List getFileFilters() {
- return Collections.unmodifiableList(this.fileFilters);
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean removeFileFilter(final IOFileFilter ioFileFilter) {
- return this.fileFilters.remove(ioFileFilter);
- }
-
- /**
- * {@inheritDoc}
- */
- public void setFileFilters(final List fileFilters) {
- this.fileFilters = new ArrayList(fileFilters);
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean accept(final File file) {
- if (this.fileFilters.size() == 0) {
- return false;
- }
- for (Iterator iter = this.fileFilters.iterator(); iter.hasNext();) {
- IOFileFilter fileFilter = (IOFileFilter) iter.next();
- if (!fileFilter.accept(file)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean accept(final File file, final String name) {
- if (this.fileFilters.size() == 0) {
- return false;
- }
- for (Iterator iter = this.fileFilters.iterator(); iter.hasNext();) {
- IOFileFilter fileFilter = (IOFileFilter) iter.next();
- if (!fileFilter.accept(file, name)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Provide a String representaion of this file filter.
- *
- * @return a String representaion
- */
- public String toString() {
- StringBuffer buffer = new StringBuffer();
- buffer.append(super.toString());
- buffer.append("(");
- if (fileFilters != null) {
- for (int i = 0; i < fileFilters.size(); i++) {
- if (i > 0) {
- buffer.append(",");
- }
- Object filter = fileFilters.get(i);
- buffer.append(filter == null ? "null" : filter.toString());
- }
- }
- buffer.append(")");
- return buffer.toString();
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/CanReadFileFilter.java b/src/org/apache/commons/io/filefilter/CanReadFileFilter.java
deleted file mode 100644
index a9c132570..000000000
--- a/src/org/apache/commons/io/filefilter/CanReadFileFilter.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * This filter accepts <code>File</code>s that can be read.
- * <p>
- * Example, showing how to print out a list of the
- * current directory's <i>readable</i> files:
- *
- * <pre>
- * File dir = new File(".");
- * String[] files = dir.list( CanReadFileFilter.CAN_READ );
- * for ( int i = 0; i &lt; files.length; i++ ) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * <p>
- * Example, showing how to print out a list of the
- * current directory's <i>un-readable</i> files:
- *
- * <pre>
- * File dir = new File(".");
- * String[] files = dir.list( CanReadFileFilter.CANNOT_READ );
- * for ( int i = 0; i &lt; files.length; i++ ) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * <p>
- * Example, showing how to print out a list of the
- * current directory's <i>read-only</i> files:
- *
- * <pre>
- * File dir = new File(".");
- * String[] files = dir.list( CanReadFileFilter.READ_ONLY );
- * for ( int i = 0; i &lt; files.length; i++ ) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * @since Commons IO 1.3
- * @version $Revision: 587916 $
- */
-public class CanReadFileFilter extends AbstractFileFilter implements Serializable {
-
- /** Singleton instance of <i>readable</i> filter */
- public static final IOFileFilter CAN_READ = new CanReadFileFilter();
-
- /** Singleton instance of not <i>readable</i> filter */
- public static final IOFileFilter CANNOT_READ = new NotFileFilter(CAN_READ);
-
- /** Singleton instance of <i>read-only</i> filter */
- public static final IOFileFilter READ_ONLY = new AndFileFilter(CAN_READ,
- CanWriteFileFilter.CANNOT_WRITE);
-
- /**
- * Restrictive consructor.
- */
- protected CanReadFileFilter() {
- }
-
- /**
- * Checks to see if the file can be read.
- *
- * @param file the File to check.
- * @return <code>true</code> if the file can be
- * read, otherwise <code>false</code>.
- */
- public boolean accept(File file) {
- return file.canRead();
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/CanWriteFileFilter.java b/src/org/apache/commons/io/filefilter/CanWriteFileFilter.java
deleted file mode 100644
index da664f25c..000000000
--- a/src/org/apache/commons/io/filefilter/CanWriteFileFilter.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * This filter accepts <code>File</code>s that can be written to.
- * <p>
- * Example, showing how to print out a list of the
- * current directory's <i>writable</i> files:
- *
- * <pre>
- * File dir = new File(".");
- * String[] files = dir.list( CanWriteFileFilter.CAN_WRITE );
- * for ( int i = 0; i &lt; files.length; i++ ) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * <p>
- * Example, showing how to print out a list of the
- * current directory's <i>un-writable</i> files:
- *
- * <pre>
- * File dir = new File(".");
- * String[] files = dir.list( CanWriteFileFilter.CANNOT_WRITE );
- * for ( int i = 0; i &lt; files.length; i++ ) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * <p>
- * <b>N.B.</b> For read-only files, use
- * <code>CanReadFileFilter.READ_ONLY</code>.
- *
- * @since Commons IO 1.3
- * @version $Revision: 587916 $
- */
-public class CanWriteFileFilter extends AbstractFileFilter implements Serializable {
-
- /** Singleton instance of <i>writable</i> filter */
- public static final IOFileFilter CAN_WRITE = new CanWriteFileFilter();
-
- /** Singleton instance of not <i>writable</i> filter */
- public static final IOFileFilter CANNOT_WRITE = new NotFileFilter(CAN_WRITE);
-
- /**
- * Restrictive consructor.
- */
- protected CanWriteFileFilter() {
- }
-
- /**
- * Checks to see if the file can be written to.
- *
- * @param file the File to check
- * @return <code>true</code> if the file can be
- * written to, otherwise <code>false</code>.
- */
- public boolean accept(File file) {
- return file.canWrite();
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/ConditionalFileFilter.java b/src/org/apache/commons/io/filefilter/ConditionalFileFilter.java
deleted file mode 100644
index ce1419ee8..000000000
--- a/src/org/apache/commons/io/filefilter/ConditionalFileFilter.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.util.List;
-
-/**
- * Defines operations for conditional file filters.
- *
- * @since Commons IO 1.1
- * @version $Revision: 437567 $ $Date: 2006-08-28 07:39:07 +0100 (Mon, 28 Aug 2006) $
- *
- * @author Steven Caswell
- */
-public interface ConditionalFileFilter {
-
- /**
- * Adds the specified file filter to the list of file filters at the end of
- * the list.
- *
- * @param ioFileFilter the filter to be added
- * @since Commons IO 1.1
- */
- public void addFileFilter(IOFileFilter ioFileFilter);
-
- /**
- * Returns this conditional file filter's list of file filters.
- *
- * @return the file filter list
- * @since Commons IO 1.1
- */
- public List getFileFilters();
-
- /**
- * Removes the specified file filter.
- *
- * @param ioFileFilter filter to be removed
- * @return <code>true</code> if the filter was found in the list,
- * <code>false</code> otherwise
- * @since Commons IO 1.1
- */
- public boolean removeFileFilter(IOFileFilter ioFileFilter);
-
- /**
- * Sets the list of file filters, replacing any previously configured
- * file filters on this filter.
- *
- * @param fileFilters the list of filters
- * @since Commons IO 1.1
- */
- public void setFileFilters(List fileFilters);
-
-}
diff --git a/src/org/apache/commons/io/filefilter/DelegateFileFilter.java b/src/org/apache/commons/io/filefilter/DelegateFileFilter.java
deleted file mode 100644
index c2d67c469..000000000
--- a/src/org/apache/commons/io/filefilter/DelegateFileFilter.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FilenameFilter;
-import java.io.Serializable;
-
-/**
- * This class turns a Java FileFilter or FilenameFilter into an IO FileFilter.
- *
- * @since Commons IO 1.0
- * @version $Revision: 591058 $ $Date: 2007-11-01 15:47:05 +0000 (Thu, 01 Nov 2007) $
- *
- * @author Stephen Colebourne
- */
-public class DelegateFileFilter extends AbstractFileFilter implements Serializable {
-
- /** The Filename filter */
- private final FilenameFilter filenameFilter;
- /** The File filter */
- private final FileFilter fileFilter;
-
- /**
- * Constructs a delegate file filter around an existing FilenameFilter.
- *
- * @param filter the filter to decorate
- */
- public DelegateFileFilter(FilenameFilter filter) {
- if (filter == null) {
- throw new IllegalArgumentException("The FilenameFilter must not be null");
- }
- this.filenameFilter = filter;
- this.fileFilter = null;
- }
-
- /**
- * Constructs a delegate file filter around an existing FileFilter.
- *
- * @param filter the filter to decorate
- */
- public DelegateFileFilter(FileFilter filter) {
- if (filter == null) {
- throw new IllegalArgumentException("The FileFilter must not be null");
- }
- this.fileFilter = filter;
- this.filenameFilter = null;
- }
-
- /**
- * Checks the filter.
- *
- * @param file the file to check
- * @return true if the filter matches
- */
- public boolean accept(File file) {
- if (fileFilter != null) {
- return fileFilter.accept(file);
- } else {
- return super.accept(file);
- }
- }
-
- /**
- * Checks the filter.
- *
- * @param dir the directory
- * @param name the filename in the directory
- * @return true if the filter matches
- */
- public boolean accept(File dir, String name) {
- if (filenameFilter != null) {
- return filenameFilter.accept(dir, name);
- } else {
- return super.accept(dir, name);
- }
- }
-
- /**
- * Provide a String representaion of this file filter.
- *
- * @return a String representaion
- */
- public String toString() {
- String delegate = (fileFilter != null ? fileFilter.toString() : filenameFilter.toString());
- return super.toString() + "(" + delegate + ")";
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/DirectoryFileFilter.java b/src/org/apache/commons/io/filefilter/DirectoryFileFilter.java
deleted file mode 100644
index 3412e7bef..000000000
--- a/src/org/apache/commons/io/filefilter/DirectoryFileFilter.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * This filter accepts <code>File</code>s that are directories.
- * <p>
- * For example, here is how to print out a list of the
- * current directory's subdirectories:
- *
- * <pre>
- * File dir = new File(".");
- * String[] files = dir.list( DirectoryFileFilter.INSTANCE );
- * for ( int i = 0; i &lt; files.length; i++ ) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * @since Commons IO 1.0
- * @version $Revision: 587916 $ $Date: 2007-10-24 16:53:07 +0100 (Wed, 24 Oct 2007) $
- *
- * @author Stephen Colebourne
- * @author Peter Donald
- */
-public class DirectoryFileFilter extends AbstractFileFilter implements Serializable {
-
- /**
- * Singleton instance of directory filter.
- * @since Commons IO 1.3
- */
- public static final IOFileFilter DIRECTORY = new DirectoryFileFilter();
- /**
- * Singleton instance of directory filter.
- * Please use the identical DirectoryFileFilter.DIRECTORY constant.
- * The new name is more JDK 1.5 friendly as it doesn't clash with other
- * values when using static imports.
- */
- public static final IOFileFilter INSTANCE = DIRECTORY;
-
- /**
- * Restrictive consructor.
- */
- protected DirectoryFileFilter() {
- }
-
- /**
- * Checks to see if the file is a directory.
- *
- * @param file the File to check
- * @return true if the file is a directory
- */
- public boolean accept(File file) {
- return file.isDirectory();
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/EmptyFileFilter.java b/src/org/apache/commons/io/filefilter/EmptyFileFilter.java
deleted file mode 100644
index e88a862d4..000000000
--- a/src/org/apache/commons/io/filefilter/EmptyFileFilter.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * This filter accepts files or directories that are empty.
- * <p>
- * If the <code>File</code> is a directory it checks that
- * it contains no files.
- * <p>
- * Example, showing how to print out a list of the
- * current directory's empty files/directories:
- *
- * <pre>
- * File dir = new File(".");
- * String[] files = dir.list( EmptyFileFilter.EMPTY );
- * for ( int i = 0; i &lt; files.length; i++ ) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * <p>
- * Example, showing how to print out a list of the
- * current directory's non-empty files/directories:
- *
- * <pre>
- * File dir = new File(".");
- * String[] files = dir.list( EmptyFileFilter.NOT_EMPTY );
- * for ( int i = 0; i &lt; files.length; i++ ) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * @since Commons IO 1.3
- * @version $Revision: 587916 $
- */
-public class EmptyFileFilter extends AbstractFileFilter implements Serializable {
-
- /** Singleton instance of <i>empty</i> filter */
- public static final IOFileFilter EMPTY = new EmptyFileFilter();
-
- /** Singleton instance of <i>not-empty</i> filter */
- public static final IOFileFilter NOT_EMPTY = new NotFileFilter(EMPTY);
-
- /**
- * Restrictive consructor.
- */
- protected EmptyFileFilter() {
- }
-
- /**
- * Checks to see if the file is empty.
- *
- * @param file the file or directory to check
- * @return <code>true</code> if the file or directory
- * is <i>empty</i>, otherwise <code>false</code>.
- */
- public boolean accept(File file) {
- if (file.isDirectory()) {
- File[] files = file.listFiles();
- return (files == null || files.length == 0);
- } else {
- return (file.length() == 0);
- }
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/FalseFileFilter.java b/src/org/apache/commons/io/filefilter/FalseFileFilter.java
deleted file mode 100644
index 8a87d4092..000000000
--- a/src/org/apache/commons/io/filefilter/FalseFileFilter.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * A file filter that always returns false.
- *
- * @since Commons IO 1.0
- * @version $Revision: 587978 $ $Date: 2007-10-24 20:36:51 +0100 (Wed, 24 Oct 2007) $
- *
- * @author Stephen Colebourne
- */
-public class FalseFileFilter implements IOFileFilter, Serializable {
-
- /**
- * Singleton instance of false filter.
- * @since Commons IO 1.3
- */
- public static final IOFileFilter FALSE = new FalseFileFilter();
- /**
- * Singleton instance of false filter.
- * Please use the identical FalseFileFilter.FALSE constant.
- * The new name is more JDK 1.5 friendly as it doesn't clash with other
- * values when using static imports.
- */
- public static final IOFileFilter INSTANCE = FALSE;
-
- /**
- * Restrictive consructor.
- */
- protected FalseFileFilter() {
- }
-
- /**
- * Returns false.
- *
- * @param file the file to check
- * @return false
- */
- public boolean accept(File file) {
- return false;
- }
-
- /**
- * Returns false.
- *
- * @param dir the directory to check
- * @param name the filename
- * @return false
- */
- public boolean accept(File dir, String name) {
- return false;
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/FileFileFilter.java b/src/org/apache/commons/io/filefilter/FileFileFilter.java
deleted file mode 100644
index 0d49eddd4..000000000
--- a/src/org/apache/commons/io/filefilter/FileFileFilter.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * This filter accepts <code>File</code>s that are files (not directories).
- * <p>
- * For example, here is how to print out a list of the real files
- * within the current directory:
- *
- * <pre>
- * File dir = new File(".");
- * String[] files = dir.list( FileFileFilter.FILE );
- * for ( int i = 0; i &lt; files.length; i++ ) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * @since Commons IO 1.3
- * @version $Revision: 155419 $ $Date: 2007-10-24 16:53:07 +0100 (Wed, 24 Oct 2007) $
- */
-public class FileFileFilter extends AbstractFileFilter implements Serializable {
-
- /** Singleton instance of file filter */
- public static final IOFileFilter FILE = new FileFileFilter();
-
- /**
- * Restrictive consructor.
- */
- protected FileFileFilter() {
- }
-
- /**
- * Checks to see if the file is a file.
- *
- * @param file the File to check
- * @return true if the file is a file
- */
- public boolean accept(File file) {
- return file.isFile();
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/FileFilterUtils.java b/src/org/apache/commons/io/filefilter/FileFilterUtils.java
deleted file mode 100644
index 71c37b1d2..000000000
--- a/src/org/apache/commons/io/filefilter/FileFilterUtils.java
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FilenameFilter;
-import java.util.Date;
-
-/**
- * Useful utilities for working with file filters. It provides access to all
- * file filter implementations in this package so you don't have to import
- * every class you use.
- *
- * @since Commons IO 1.0
- * @version $Id: FileFilterUtils.java 609286 2008-01-06 10:01:26Z scolebourne $
- *
- * @author Stephen Colebourne
- * @author Jeremias Maerki
- * @author Masato Tezuka
- * @author Rahul Akolkar
- */
-public class FileFilterUtils {
-
- /**
- * FileFilterUtils is not normally instantiated.
- */
- public FileFilterUtils() {
- }
-
- //-----------------------------------------------------------------------
- /**
- * Returns a filter that returns true if the filename starts with the specified text.
- *
- * @param prefix the filename prefix
- * @return a prefix checking filter
- */
- public static IOFileFilter prefixFileFilter(String prefix) {
- return new PrefixFileFilter(prefix);
- }
-
- /**
- * Returns a filter that returns true if the filename ends with the specified text.
- *
- * @param suffix the filename suffix
- * @return a suffix checking filter
- */
- public static IOFileFilter suffixFileFilter(String suffix) {
- return new SuffixFileFilter(suffix);
- }
-
- /**
- * Returns a filter that returns true if the filename matches the specified text.
- *
- * @param name the filename
- * @return a name checking filter
- */
- public static IOFileFilter nameFileFilter(String name) {
- return new NameFileFilter(name);
- }
-
- /**
- * Returns a filter that checks if the file is a directory.
- *
- * @return file filter that accepts only directories and not files
- */
- public static IOFileFilter directoryFileFilter() {
- return DirectoryFileFilter.DIRECTORY;
- }
-
- /**
- * Returns a filter that checks if the file is a file (and not a directory).
- *
- * @return file filter that accepts only files and not directories
- */
- public static IOFileFilter fileFileFilter() {
- return FileFileFilter.FILE;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Returns a filter that ANDs the two specified filters.
- *
- * @param filter1 the first filter
- * @param filter2 the second filter
- * @return a filter that ANDs the two specified filters
- */
- public static IOFileFilter andFileFilter(IOFileFilter filter1, IOFileFilter filter2) {
- return new AndFileFilter(filter1, filter2);
- }
-
- /**
- * Returns a filter that ORs the two specified filters.
- *
- * @param filter1 the first filter
- * @param filter2 the second filter
- * @return a filter that ORs the two specified filters
- */
- public static IOFileFilter orFileFilter(IOFileFilter filter1, IOFileFilter filter2) {
- return new OrFileFilter(filter1, filter2);
- }
-
- /**
- * Returns a filter that NOTs the specified filter.
- *
- * @param filter the filter to invert
- * @return a filter that NOTs the specified filter
- */
- public static IOFileFilter notFileFilter(IOFileFilter filter) {
- return new NotFileFilter(filter);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Returns a filter that always returns true.
- *
- * @return a true filter
- */
- public static IOFileFilter trueFileFilter() {
- return TrueFileFilter.TRUE;
- }
-
- /**
- * Returns a filter that always returns false.
- *
- * @return a false filter
- */
- public static IOFileFilter falseFileFilter() {
- return FalseFileFilter.FALSE;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Returns an <code>IOFileFilter</code> that wraps the
- * <code>FileFilter</code> instance.
- *
- * @param filter the filter to be wrapped
- * @return a new filter that implements IOFileFilter
- */
- public static IOFileFilter asFileFilter(FileFilter filter) {
- return new DelegateFileFilter(filter);
- }
-
- /**
- * Returns an <code>IOFileFilter</code> that wraps the
- * <code>FilenameFilter</code> instance.
- *
- * @param filter the filter to be wrapped
- * @return a new filter that implements IOFileFilter
- */
- public static IOFileFilter asFileFilter(FilenameFilter filter) {
- return new DelegateFileFilter(filter);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Returns a filter that returns true if the file was last modified after
- * the specified cutoff time.
- *
- * @param cutoff the time threshold
- * @return an appropriately configured age file filter
- * @since Commons IO 1.2
- */
- public static IOFileFilter ageFileFilter(long cutoff) {
- return new AgeFileFilter(cutoff);
- }
-
- /**
- * Returns a filter that filters files based on a cutoff time.
- *
- * @param cutoff the time threshold
- * @param acceptOlder if true, older files get accepted, if false, newer
- * @return an appropriately configured age file filter
- * @since Commons IO 1.2
- */
- public static IOFileFilter ageFileFilter(long cutoff, boolean acceptOlder) {
- return new AgeFileFilter(cutoff, acceptOlder);
- }
-
- /**
- * Returns a filter that returns true if the file was last modified after
- * the specified cutoff date.
- *
- * @param cutoffDate the time threshold
- * @return an appropriately configured age file filter
- * @since Commons IO 1.2
- */
- public static IOFileFilter ageFileFilter(Date cutoffDate) {
- return new AgeFileFilter(cutoffDate);
- }
-
- /**
- * Returns a filter that filters files based on a cutoff date.
- *
- * @param cutoffDate the time threshold
- * @param acceptOlder if true, older files get accepted, if false, newer
- * @return an appropriately configured age file filter
- * @since Commons IO 1.2
- */
- public static IOFileFilter ageFileFilter(Date cutoffDate, boolean acceptOlder) {
- return new AgeFileFilter(cutoffDate, acceptOlder);
- }
-
- /**
- * Returns a filter that returns true if the file was last modified after
- * the specified reference file.
- *
- * @param cutoffReference the file whose last modification
- * time is usesd as the threshold age of the files
- * @return an appropriately configured age file filter
- * @since Commons IO 1.2
- */
- public static IOFileFilter ageFileFilter(File cutoffReference) {
- return new AgeFileFilter(cutoffReference);
- }
-
- /**
- * Returns a filter that filters files based on a cutoff reference file.
- *
- * @param cutoffReference the file whose last modification
- * time is usesd as the threshold age of the files
- * @param acceptOlder if true, older files get accepted, if false, newer
- * @return an appropriately configured age file filter
- * @since Commons IO 1.2
- */
- public static IOFileFilter ageFileFilter(File cutoffReference, boolean acceptOlder) {
- return new AgeFileFilter(cutoffReference, acceptOlder);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Returns a filter that returns true if the file is bigger than a certain size.
- *
- * @param threshold the file size threshold
- * @return an appropriately configured SizeFileFilter
- * @since Commons IO 1.2
- */
- public static IOFileFilter sizeFileFilter(long threshold) {
- return new SizeFileFilter(threshold);
- }
-
- /**
- * Returns a filter that filters based on file size.
- *
- * @param threshold the file size threshold
- * @param acceptLarger if true, larger files get accepted, if false, smaller
- * @return an appropriately configured SizeFileFilter
- * @since Commons IO 1.2
- */
- public static IOFileFilter sizeFileFilter(long threshold, boolean acceptLarger) {
- return new SizeFileFilter(threshold, acceptLarger);
- }
-
- /**
- * Returns a filter that accepts files whose size is &gt;= minimum size
- * and &lt;= maximum size.
- *
- * @param minSizeInclusive the minimum file size (inclusive)
- * @param maxSizeInclusive the maximum file size (inclusive)
- * @return an appropriately configured IOFileFilter
- * @since Commons IO 1.3
- */
- public static IOFileFilter sizeRangeFileFilter(long minSizeInclusive, long maxSizeInclusive ) {
- IOFileFilter minimumFilter = new SizeFileFilter(minSizeInclusive, true);
- IOFileFilter maximumFilter = new SizeFileFilter(maxSizeInclusive + 1L, false);
- return new AndFileFilter(minimumFilter, maximumFilter);
- }
-
- //-----------------------------------------------------------------------
- /* Constructed on demand and then cached */
- private static IOFileFilter cvsFilter;
-
- /* Constructed on demand and then cached */
- private static IOFileFilter svnFilter;
-
- /**
- * Decorates a filter to make it ignore CVS directories.
- * Passing in <code>null</code> will return a filter that accepts everything
- * except CVS directories.
- *
- * @param filter the filter to decorate, null means an unrestricted filter
- * @return the decorated filter, never null
- * @since Commons IO 1.1 (method existed but had bug in 1.0)
- */
- public static IOFileFilter makeCVSAware(IOFileFilter filter) {
- if (cvsFilter == null) {
- cvsFilter = notFileFilter(
- andFileFilter(directoryFileFilter(), nameFileFilter("CVS")));
- }
- if (filter == null) {
- return cvsFilter;
- } else {
- return andFileFilter(filter, cvsFilter);
- }
- }
-
- /**
- * Decorates a filter to make it ignore SVN directories.
- * Passing in <code>null</code> will return a filter that accepts everything
- * except SVN directories.
- *
- * @param filter the filter to decorate, null means an unrestricted filter
- * @return the decorated filter, never null
- * @since Commons IO 1.1
- */
- public static IOFileFilter makeSVNAware(IOFileFilter filter) {
- if (svnFilter == null) {
- svnFilter = notFileFilter(
- andFileFilter(directoryFileFilter(), nameFileFilter(".svn")));
- }
- if (filter == null) {
- return svnFilter;
- } else {
- return andFileFilter(filter, svnFilter);
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Decorates a filter so that it only applies to directories and not to files.
- *
- * @param filter the filter to decorate, null means an unrestricted filter
- * @return the decorated filter, never null
- * @since Commons IO 1.3
- */
- public static IOFileFilter makeDirectoryOnly(IOFileFilter filter) {
- if (filter == null) {
- return DirectoryFileFilter.DIRECTORY;
- }
- return new AndFileFilter(DirectoryFileFilter.DIRECTORY, filter);
- }
-
- /**
- * Decorates a filter so that it only applies to files and not to directories.
- *
- * @param filter the filter to decorate, null means an unrestricted filter
- * @return the decorated filter, never null
- * @since Commons IO 1.3
- */
- public static IOFileFilter makeFileOnly(IOFileFilter filter) {
- if (filter == null) {
- return FileFileFilter.FILE;
- }
- return new AndFileFilter(FileFileFilter.FILE, filter);
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/HiddenFileFilter.java b/src/org/apache/commons/io/filefilter/HiddenFileFilter.java
deleted file mode 100644
index 244153d5e..000000000
--- a/src/org/apache/commons/io/filefilter/HiddenFileFilter.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * This filter accepts <code>File</code>s that are hidden.
- * <p>
- * Example, showing how to print out a list of the
- * current directory's <i>hidden</i> files:
- *
- * <pre>
- * File dir = new File(".");
- * String[] files = dir.list( HiddenFileFilter.HIDDEN );
- * for ( int i = 0; i &lt; files.length; i++ ) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * <p>
- * Example, showing how to print out a list of the
- * current directory's <i>visible</i> (i.e. not hidden) files:
- *
- * <pre>
- * File dir = new File(".");
- * String[] files = dir.list( HiddenFileFilter.VISIBLE );
- * for ( int i = 0; i &lt; files.length; i++ ) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * @since Commons IO 1.3
- * @version $Revision: 587916 $
- */
-public class HiddenFileFilter extends AbstractFileFilter implements Serializable {
-
- /** Singleton instance of <i>hidden</i> filter */
- public static final IOFileFilter HIDDEN = new HiddenFileFilter();
-
- /** Singleton instance of <i>visible</i> filter */
- public static final IOFileFilter VISIBLE = new NotFileFilter(HIDDEN);
-
- /**
- * Restrictive consructor.
- */
- protected HiddenFileFilter() {
- }
-
- /**
- * Checks to see if the file is hidden.
- *
- * @param file the File to check
- * @return <code>true</code> if the file is
- * <i>hidden</i>, otherwise <code>false</code>.
- */
- public boolean accept(File file) {
- return file.isHidden();
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/IOFileFilter.java b/src/org/apache/commons/io/filefilter/IOFileFilter.java
deleted file mode 100644
index 5ebd82751..000000000
--- a/src/org/apache/commons/io/filefilter/IOFileFilter.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FilenameFilter;
-
-/**
- * An interface which brings the FileFilter and FilenameFilter
- * interfaces together.
- *
- * @since Commons IO 1.0
- * @version $Revision: 471628 $ $Date: 2006-11-06 04:06:45 +0000 (Mon, 06 Nov 2006) $
- *
- * @author Stephen Colebourne
- */
-public interface IOFileFilter extends FileFilter, FilenameFilter {
-
- /**
- * Checks to see if the File should be accepted by this filter.
- * <p>
- * Defined in {@link java.io.FileFilter}.
- *
- * @param file the File to check
- * @return true if this file matches the test
- */
- public boolean accept(File file);
-
- /**
- * Checks to see if the File should be accepted by this filter.
- * <p>
- * Defined in {@link java.io.FilenameFilter}.
- *
- * @param dir the directory File to check
- * @param name the filename within the directory to check
- * @return true if this file matches the test
- */
- public boolean accept(File dir, String name);
-
-}
diff --git a/src/org/apache/commons/io/filefilter/NameFileFilter.java b/src/org/apache/commons/io/filefilter/NameFileFilter.java
deleted file mode 100644
index fa1c80f73..000000000
--- a/src/org/apache/commons/io/filefilter/NameFileFilter.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.List;
-
-import org.apache.commons.io.IOCase;
-
-/**
- * Filters filenames for a certain name.
- * <p>
- * For example, to print all files and directories in the
- * current directory whose name is <code>Test</code>:
- *
- * <pre>
- * File dir = new File(".");
- * String[] files = dir.list( new NameFileFilter("Test") );
- * for ( int i = 0; i &lt; files.length; i++ ) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * @since Commons IO 1.0
- * @version $Revision: 606381 $ $Date: 2007-12-22 02:03:16 +0000 (Sat, 22 Dec 2007) $
- *
- * @author Stephen Colebourne
- * @author Federico Barbieri
- * @author Serge Knystautas
- * @author Peter Donald
- */
-public class NameFileFilter extends AbstractFileFilter implements Serializable {
-
- /** The filenames to search for */
- private final String[] names;
- /** Whether the comparison is case sensitive. */
- private final IOCase caseSensitivity;
-
- /**
- * Constructs a new case-sensitive name file filter for a single name.
- *
- * @param name the name to allow, must not be null
- * @throws IllegalArgumentException if the name is null
- */
- public NameFileFilter(String name) {
- this(name, null);
- }
-
- /**
- * Construct a new name file filter specifying case-sensitivity.
- *
- * @param name the name to allow, must not be null
- * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the name is null
- */
- public NameFileFilter(String name, IOCase caseSensitivity) {
- if (name == null) {
- throw new IllegalArgumentException("The wildcard must not be null");
- }
- this.names = new String[] {name};
- this.caseSensitivity = (caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity);
- }
-
- /**
- * Constructs a new case-sensitive name file filter for an array of names.
- * <p>
- * The array is not cloned, so could be changed after constructing the
- * instance. This would be inadvisable however.
- *
- * @param names the names to allow, must not be null
- * @throws IllegalArgumentException if the names array is null
- */
- public NameFileFilter(String[] names) {
- this(names, null);
- }
-
- /**
- * Constructs a new name file filter for an array of names specifying case-sensitivity.
- * <p>
- * The array is not cloned, so could be changed after constructing the
- * instance. This would be inadvisable however.
- *
- * @param names the names to allow, must not be null
- * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the names array is null
- */
- public NameFileFilter(String[] names, IOCase caseSensitivity) {
- if (names == null) {
- throw new IllegalArgumentException("The array of names must not be null");
- }
- this.names = names;
- this.caseSensitivity = (caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity);
- }
-
- /**
- * Constructs a new case-sensitive name file filter for a list of names.
- *
- * @param names the names to allow, must not be null
- * @throws IllegalArgumentException if the name list is null
- * @throws ClassCastException if the list does not contain Strings
- */
- public NameFileFilter(List names) {
- this(names, null);
- }
-
- /**
- * Constructs a new name file filter for a list of names specifying case-sensitivity.
- *
- * @param names the names to allow, must not be null
- * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the name list is null
- * @throws ClassCastException if the list does not contain Strings
- */
- public NameFileFilter(List names, IOCase caseSensitivity) {
- if (names == null) {
- throw new IllegalArgumentException("The list of names must not be null");
- }
- this.names = (String[]) names.toArray(new String[names.size()]);
- this.caseSensitivity = (caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Checks to see if the filename matches.
- *
- * @param file the File to check
- * @return true if the filename matches
- */
- public boolean accept(File file) {
- String name = file.getName();
- for (int i = 0; i < this.names.length; i++) {
- if (caseSensitivity.checkEquals(name, names[i])) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks to see if the filename matches.
- *
- * @param file the File directory
- * @param name the filename
- * @return true if the filename matches
- */
- public boolean accept(File file, String name) {
- for (int i = 0; i < names.length; i++) {
- if (caseSensitivity.checkEquals(name, names[i])) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Provide a String representaion of this file filter.
- *
- * @return a String representaion
- */
- public String toString() {
- StringBuffer buffer = new StringBuffer();
- buffer.append(super.toString());
- buffer.append("(");
- if (names != null) {
- for (int i = 0; i < names.length; i++) {
- if (i > 0) {
- buffer.append(",");
- }
- buffer.append(names[i]);
- }
- }
- buffer.append(")");
- return buffer.toString();
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/NotFileFilter.java b/src/org/apache/commons/io/filefilter/NotFileFilter.java
deleted file mode 100644
index 710c8ecf3..000000000
--- a/src/org/apache/commons/io/filefilter/NotFileFilter.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * This filter produces a logical NOT of the filters specified.
- *
- * @since Commons IO 1.0
- * @version $Revision: 591058 $ $Date: 2007-11-01 15:47:05 +0000 (Thu, 01 Nov 2007) $
- *
- * @author Stephen Colebourne
- */
-public class NotFileFilter extends AbstractFileFilter implements Serializable {
-
- /** The filter */
- private final IOFileFilter filter;
-
- /**
- * Constructs a new file filter that NOTs the result of another filters.
- *
- * @param filter the filter, must not be null
- * @throws IllegalArgumentException if the filter is null
- */
- public NotFileFilter(IOFileFilter filter) {
- if (filter == null) {
- throw new IllegalArgumentException("The filter must not be null");
- }
- this.filter = filter;
- }
-
- /**
- * Checks to see if both filters are true.
- *
- * @param file the File to check
- * @return true if the filter returns false
- */
- public boolean accept(File file) {
- return ! filter.accept(file);
- }
-
- /**
- * Checks to see if both filters are true.
- *
- * @param file the File directory
- * @param name the filename
- * @return true if the filter returns false
- */
- public boolean accept(File file, String name) {
- return ! filter.accept(file, name);
- }
-
- /**
- * Provide a String representaion of this file filter.
- *
- * @return a String representaion
- */
- public String toString() {
- return super.toString() + "(" + filter.toString() + ")";
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/OrFileFilter.java b/src/org/apache/commons/io/filefilter/OrFileFilter.java
deleted file mode 100644
index 59cc0f2b0..000000000
--- a/src/org/apache/commons/io/filefilter/OrFileFilter.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * A {@link java.io.FileFilter} providing conditional OR logic across a list of
- * file filters. This filter returns <code>true</code> if any filters in the
- * list return <code>true</code>. Otherwise, it returns <code>false</code>.
- * Checking of the file filter list stops when the first filter returns
- * <code>true</code>.
- *
- * @since Commons IO 1.0
- * @version $Revision: 606381 $ $Date: 2007-12-22 02:03:16 +0000 (Sat, 22 Dec 2007) $
- *
- * @author Steven Caswell
- */
-public class OrFileFilter
- extends AbstractFileFilter
- implements ConditionalFileFilter, Serializable {
-
- /** The list of file filters. */
- private List fileFilters;
-
- /**
- * Constructs a new instance of <code>OrFileFilter</code>.
- *
- * @since Commons IO 1.1
- */
- public OrFileFilter() {
- this.fileFilters = new ArrayList();
- }
-
- /**
- * Constructs a new instance of <code>OrFileFilter</code>
- * with the specified filters.
- *
- * @param fileFilters the file filters for this filter, copied, null ignored
- * @since Commons IO 1.1
- */
- public OrFileFilter(final List fileFilters) {
- if (fileFilters == null) {
- this.fileFilters = new ArrayList();
- } else {
- this.fileFilters = new ArrayList(fileFilters);
- }
- }
-
- /**
- * Constructs a new file filter that ORs the result of two other filters.
- *
- * @param filter1 the first filter, must not be null
- * @param filter2 the second filter, must not be null
- * @throws IllegalArgumentException if either filter is null
- */
- public OrFileFilter(IOFileFilter filter1, IOFileFilter filter2) {
- if (filter1 == null || filter2 == null) {
- throw new IllegalArgumentException("The filters must not be null");
- }
- this.fileFilters = new ArrayList();
- addFileFilter(filter1);
- addFileFilter(filter2);
- }
-
- /**
- * {@inheritDoc}
- */
- public void addFileFilter(final IOFileFilter ioFileFilter) {
- this.fileFilters.add(ioFileFilter);
- }
-
- /**
- * {@inheritDoc}
- */
- public List getFileFilters() {
- return Collections.unmodifiableList(this.fileFilters);
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean removeFileFilter(IOFileFilter ioFileFilter) {
- return this.fileFilters.remove(ioFileFilter);
- }
-
- /**
- * {@inheritDoc}
- */
- public void setFileFilters(final List fileFilters) {
- this.fileFilters = fileFilters;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean accept(final File file) {
- for (Iterator iter = this.fileFilters.iterator(); iter.hasNext();) {
- IOFileFilter fileFilter = (IOFileFilter) iter.next();
- if (fileFilter.accept(file)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean accept(final File file, final String name) {
- for (Iterator iter = this.fileFilters.iterator(); iter.hasNext();) {
- IOFileFilter fileFilter = (IOFileFilter) iter.next();
- if (fileFilter.accept(file, name)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Provide a String representaion of this file filter.
- *
- * @return a String representaion
- */
- public String toString() {
- StringBuffer buffer = new StringBuffer();
- buffer.append(super.toString());
- buffer.append("(");
- if (fileFilters != null) {
- for (int i = 0; i < fileFilters.size(); i++) {
- if (i > 0) {
- buffer.append(",");
- }
- Object filter = fileFilters.get(i);
- buffer.append(filter == null ? "null" : filter.toString());
- }
- }
- buffer.append(")");
- return buffer.toString();
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/PrefixFileFilter.java b/src/org/apache/commons/io/filefilter/PrefixFileFilter.java
deleted file mode 100644
index 0b6fcb961..000000000
--- a/src/org/apache/commons/io/filefilter/PrefixFileFilter.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.List;
-
-import org.apache.commons.io.IOCase;
-
-/**
- * Filters filenames for a certain prefix.
- * <p>
- * For example, to print all files and directories in the
- * current directory whose name starts with <code>Test</code>:
- *
- * <pre>
- * File dir = new File(".");
- * String[] files = dir.list( new PrefixFileFilter("Test") );
- * for ( int i = 0; i &lt; files.length; i++ ) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * @since Commons IO 1.0
- * @version $Revision: 606381 $ $Date: 2007-12-22 02:03:16 +0000 (Sat, 22 Dec 2007) $
- *
- * @author Stephen Colebourne
- * @author Federico Barbieri
- * @author Serge Knystautas
- * @author Peter Donald
- */
-public class PrefixFileFilter extends AbstractFileFilter implements Serializable {
-
- /** The filename prefixes to search for */
- private final String[] prefixes;
-
- /** Whether the comparison is case sensitive. */
- private final IOCase caseSensitivity;
-
- /**
- * Constructs a new Prefix file filter for a single prefix.
- *
- * @param prefix the prefix to allow, must not be null
- * @throws IllegalArgumentException if the prefix is null
- */
- public PrefixFileFilter(String prefix) {
- this(prefix, IOCase.SENSITIVE);
- }
-
- /**
- * Constructs a new Prefix file filter for a single prefix
- * specifying case-sensitivity.
- *
- * @param prefix the prefix to allow, must not be null
- * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the prefix is null
- * @since Commons IO 1.4
- */
- public PrefixFileFilter(String prefix, IOCase caseSensitivity) {
- if (prefix == null) {
- throw new IllegalArgumentException("The prefix must not be null");
- }
- this.prefixes = new String[] {prefix};
- this.caseSensitivity = (caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity);
- }
-
- /**
- * Constructs a new Prefix file filter for any of an array of prefixes.
- * <p>
- * The array is not cloned, so could be changed after constructing the
- * instance. This would be inadvisable however.
- *
- * @param prefixes the prefixes to allow, must not be null
- * @throws IllegalArgumentException if the prefix array is null
- */
- public PrefixFileFilter(String[] prefixes) {
- this(prefixes, IOCase.SENSITIVE);
- }
-
- /**
- * Constructs a new Prefix file filter for any of an array of prefixes
- * specifying case-sensitivity.
- * <p>
- * The array is not cloned, so could be changed after constructing the
- * instance. This would be inadvisable however.
- *
- * @param prefixes the prefixes to allow, must not be null
- * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the prefix is null
- * @since Commons IO 1.4
- */
- public PrefixFileFilter(String[] prefixes, IOCase caseSensitivity) {
- if (prefixes == null) {
- throw new IllegalArgumentException("The array of prefixes must not be null");
- }
- this.prefixes = prefixes;
- this.caseSensitivity = (caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity);
- }
-
- /**
- * Constructs a new Prefix file filter for a list of prefixes.
- *
- * @param prefixes the prefixes to allow, must not be null
- * @throws IllegalArgumentException if the prefix list is null
- * @throws ClassCastException if the list does not contain Strings
- */
- public PrefixFileFilter(List prefixes) {
- this(prefixes, IOCase.SENSITIVE);
- }
-
- /**
- * Constructs a new Prefix file filter for a list of prefixes
- * specifying case-sensitivity.
- *
- * @param prefixes the prefixes to allow, must not be null
- * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the prefix list is null
- * @throws ClassCastException if the list does not contain Strings
- * @since Commons IO 1.4
- */
- public PrefixFileFilter(List prefixes, IOCase caseSensitivity) {
- if (prefixes == null) {
- throw new IllegalArgumentException("The list of prefixes must not be null");
- }
- this.prefixes = (String[]) prefixes.toArray(new String[prefixes.size()]);
- this.caseSensitivity = (caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity);
- }
-
- /**
- * Checks to see if the filename starts with the prefix.
- *
- * @param file the File to check
- * @return true if the filename starts with one of our prefixes
- */
- public boolean accept(File file) {
- String name = file.getName();
- for (int i = 0; i < this.prefixes.length; i++) {
- if (caseSensitivity.checkStartsWith(name, prefixes[i])) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks to see if the filename starts with the prefix.
- *
- * @param file the File directory
- * @param name the filename
- * @return true if the filename starts with one of our prefixes
- */
- public boolean accept(File file, String name) {
- for (int i = 0; i < prefixes.length; i++) {
- if (caseSensitivity.checkStartsWith(name, prefixes[i])) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Provide a String representaion of this file filter.
- *
- * @return a String representaion
- */
- public String toString() {
- StringBuffer buffer = new StringBuffer();
- buffer.append(super.toString());
- buffer.append("(");
- if (prefixes != null) {
- for (int i = 0; i < prefixes.length; i++) {
- if (i > 0) {
- buffer.append(",");
- }
- buffer.append(prefixes[i]);
- }
- }
- buffer.append(")");
- return buffer.toString();
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/RegexFileFilter.java b/src/org/apache/commons/io/filefilter/RegexFileFilter.java
deleted file mode 100644
index b49a1bd3b..000000000
--- a/src/org/apache/commons/io/filefilter/RegexFileFilter.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.regex.Pattern;
-
-import org.apache.commons.io.IOCase;
-
-/**
- * Filters files using supplied regular expression(s).
- * <p/>
- * See java.util.regex.Pattern for regex matching rules
- * <p/>
- *
- * <p/>
- * e.g.
- * <pre>
- * File dir = new File(".");
- * FileFilter fileFilter = new RegexFileFilter("^.*[tT]est(-\\d+)?\\.java$");
- * File[] files = dir.listFiles(fileFilter);
- * for (int i = 0; i < files.length; i++) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * @author Oliver Siegmar
- * @version $Revision: 606381 $
- * @since Commons IO 1.4
- */
-public class RegexFileFilter extends AbstractFileFilter implements Serializable {
-
- /** The regular expression pattern that will be used to match filenames */
- private final Pattern pattern;
-
- /**
- * Construct a new regular expression filter.
- *
- * @param pattern regular string expression to match
- * @throws IllegalArgumentException if the pattern is null
- */
- public RegexFileFilter(String pattern) {
- if (pattern == null) {
- throw new IllegalArgumentException("Pattern is missing");
- }
-
- this.pattern = Pattern.compile(pattern);
- }
-
- /**
- * Construct a new regular expression filter with the specified flags case sensitivity.
- *
- * @param pattern regular string expression to match
- * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the pattern is null
- */
- public RegexFileFilter(String pattern, IOCase caseSensitivity) {
- if (pattern == null) {
- throw new IllegalArgumentException("Pattern is missing");
- }
- int flags = 0;
- if (caseSensitivity != null && !caseSensitivity.isCaseSensitive()) {
- flags = Pattern.CASE_INSENSITIVE;
- }
- this.pattern = Pattern.compile(pattern, flags);
- }
-
- /**
- * Construct a new regular expression filter with the specified flags.
- *
- * @param pattern regular string expression to match
- * @param flags pattern flags - e.g. {@link Pattern#CASE_INSENSITIVE}
- * @throws IllegalArgumentException if the pattern is null
- */
- public RegexFileFilter(String pattern, int flags) {
- if (pattern == null) {
- throw new IllegalArgumentException("Pattern is missing");
- }
- this.pattern = Pattern.compile(pattern, flags);
- }
-
- /**
- * Construct a new regular expression filter for a compiled regular expression
- *
- * @param pattern regular expression to match
- * @throws IllegalArgumentException if the pattern is null
- */
- public RegexFileFilter(Pattern pattern) {
- if (pattern == null) {
- throw new IllegalArgumentException("Pattern is missing");
- }
-
- this.pattern = pattern;
- }
-
- /**
- * Checks to see if the filename matches one of the regular expressions.
- *
- * @param dir the file directory
- * @param name the filename
- * @return true if the filename matches one of the regular expressions
- */
- public boolean accept(File dir, String name) {
- return (pattern.matcher(name).matches());
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/SizeFileFilter.java b/src/org/apache/commons/io/filefilter/SizeFileFilter.java
deleted file mode 100644
index 614e4243f..000000000
--- a/src/org/apache/commons/io/filefilter/SizeFileFilter.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * Filters files based on size, can filter either smaller files or
- * files equal to or larger than a given threshold.
- * <p>
- * For example, to print all files and directories in the
- * current directory whose size is greater than 1 MB:
- *
- * <pre>
- * File dir = new File(".");
- * String[] files = dir.list( new SizeFileFilter(1024 * 1024) );
- * for ( int i = 0; i &lt; files.length; i++ ) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * @author Rahul Akolkar
- * @version $Id: SizeFileFilter.java 591058 2007-11-01 15:47:05Z niallp $
- * @since Commons IO 1.2
- */
-public class SizeFileFilter extends AbstractFileFilter implements Serializable {
-
- /** The size threshold. */
- private final long size;
- /** Whether the files accepted will be larger or smaller. */
- private final boolean acceptLarger;
-
- /**
- * Constructs a new size file filter for files equal to or
- * larger than a certain size.
- *
- * @param size the threshold size of the files
- * @throws IllegalArgumentException if the size is negative
- */
- public SizeFileFilter(long size) {
- this(size, true);
- }
-
- /**
- * Constructs a new size file filter for files based on a certain size
- * threshold.
- *
- * @param size the threshold size of the files
- * @param acceptLarger if true, files equal to or larger are accepted,
- * otherwise smaller ones (but not equal to)
- * @throws IllegalArgumentException if the size is negative
- */
- public SizeFileFilter(long size, boolean acceptLarger) {
- if (size < 0) {
- throw new IllegalArgumentException("The size must be non-negative");
- }
- this.size = size;
- this.acceptLarger = acceptLarger;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Checks to see if the size of the file is favorable.
- * <p>
- * If size equals threshold and smaller files are required,
- * file <b>IS NOT</b> selected.
- * If size equals threshold and larger files are required,
- * file <b>IS</b> selected.
- *
- * @param file the File to check
- * @return true if the filename matches
- */
- public boolean accept(File file) {
- boolean smaller = file.length() < size;
- return acceptLarger ? !smaller : smaller;
- }
-
- /**
- * Provide a String representaion of this file filter.
- *
- * @return a String representaion
- */
- public String toString() {
- String condition = acceptLarger ? ">=" : "<";
- return super.toString() + "(" + condition + size + ")";
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/SuffixFileFilter.java b/src/org/apache/commons/io/filefilter/SuffixFileFilter.java
deleted file mode 100644
index bee34402c..000000000
--- a/src/org/apache/commons/io/filefilter/SuffixFileFilter.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.List;
-
-import org.apache.commons.io.IOCase;
-
-/**
- * Filters files based on the suffix (what the filename ends with).
- * This is used in retrieving all the files of a particular type.
- * <p>
- * For example, to retrieve and print all <code>*.java</code> files
- * in the current directory:
- *
- * <pre>
- * File dir = new File(".");
- * String[] files = dir.list( new SuffixFileFilter(".java") );
- * for (int i = 0; i &lt; files.length; i++) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * @since Commons IO 1.0
- * @version $Revision: 606381 $ $Date: 2007-12-22 02:03:16 +0000 (Sat, 22 Dec 2007) $
- *
- * @author Stephen Colebourne
- * @author Federico Barbieri
- * @author Serge Knystautas
- * @author Peter Donald
- */
-public class SuffixFileFilter extends AbstractFileFilter implements Serializable {
-
- /** The filename suffixes to search for */
- private final String[] suffixes;
-
- /** Whether the comparison is case sensitive. */
- private final IOCase caseSensitivity;
-
- /**
- * Constructs a new Suffix file filter for a single extension.
- *
- * @param suffix the suffix to allow, must not be null
- * @throws IllegalArgumentException if the suffix is null
- */
- public SuffixFileFilter(String suffix) {
- this(suffix, IOCase.SENSITIVE);
- }
-
- /**
- * Constructs a new Suffix file filter for a single extension
- * specifying case-sensitivity.
- *
- * @param suffix the suffix to allow, must not be null
- * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the suffix is null
- * @since Commons IO 1.4
- */
- public SuffixFileFilter(String suffix, IOCase caseSensitivity) {
- if (suffix == null) {
- throw new IllegalArgumentException("The suffix must not be null");
- }
- this.suffixes = new String[] {suffix};
- this.caseSensitivity = (caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity);
- }
-
- /**
- * Constructs a new Suffix file filter for an array of suffixs.
- * <p>
- * The array is not cloned, so could be changed after constructing the
- * instance. This would be inadvisable however.
- *
- * @param suffixes the suffixes to allow, must not be null
- * @throws IllegalArgumentException if the suffix array is null
- */
- public SuffixFileFilter(String[] suffixes) {
- this(suffixes, IOCase.SENSITIVE);
- }
-
- /**
- * Constructs a new Suffix file filter for an array of suffixs
- * specifying case-sensitivity.
- * <p>
- * The array is not cloned, so could be changed after constructing the
- * instance. This would be inadvisable however.
- *
- * @param suffixes the suffixes to allow, must not be null
- * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the suffix array is null
- * @since Commons IO 1.4
- */
- public SuffixFileFilter(String[] suffixes, IOCase caseSensitivity) {
- if (suffixes == null) {
- throw new IllegalArgumentException("The array of suffixes must not be null");
- }
- this.suffixes = suffixes;
- this.caseSensitivity = (caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity);
- }
-
- /**
- * Constructs a new Suffix file filter for a list of suffixes.
- *
- * @param suffixes the suffixes to allow, must not be null
- * @throws IllegalArgumentException if the suffix list is null
- * @throws ClassCastException if the list does not contain Strings
- */
- public SuffixFileFilter(List suffixes) {
- this(suffixes, IOCase.SENSITIVE);
- }
-
- /**
- * Constructs a new Suffix file filter for a list of suffixes
- * specifying case-sensitivity.
- *
- * @param suffixes the suffixes to allow, must not be null
- * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the suffix list is null
- * @throws ClassCastException if the list does not contain Strings
- * @since Commons IO 1.4
- */
- public SuffixFileFilter(List suffixes, IOCase caseSensitivity) {
- if (suffixes == null) {
- throw new IllegalArgumentException("The list of suffixes must not be null");
- }
- this.suffixes = (String[]) suffixes.toArray(new String[suffixes.size()]);
- this.caseSensitivity = (caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity);
- }
-
- /**
- * Checks to see if the filename ends with the suffix.
- *
- * @param file the File to check
- * @return true if the filename ends with one of our suffixes
- */
- public boolean accept(File file) {
- String name = file.getName();
- for (int i = 0; i < this.suffixes.length; i++) {
- if (caseSensitivity.checkEndsWith(name, suffixes[i])) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks to see if the filename ends with the suffix.
- *
- * @param file the File directory
- * @param name the filename
- * @return true if the filename ends with one of our suffixes
- */
- public boolean accept(File file, String name) {
- for (int i = 0; i < this.suffixes.length; i++) {
- if (caseSensitivity.checkEndsWith(name, suffixes[i])) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Provide a String representaion of this file filter.
- *
- * @return a String representaion
- */
- public String toString() {
- StringBuffer buffer = new StringBuffer();
- buffer.append(super.toString());
- buffer.append("(");
- if (suffixes != null) {
- for (int i = 0; i < suffixes.length; i++) {
- if (i > 0) {
- buffer.append(",");
- }
- buffer.append(suffixes[i]);
- }
- }
- buffer.append(")");
- return buffer.toString();
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/TrueFileFilter.java b/src/org/apache/commons/io/filefilter/TrueFileFilter.java
deleted file mode 100644
index be1b13a7e..000000000
--- a/src/org/apache/commons/io/filefilter/TrueFileFilter.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * A file filter that always returns true.
- *
- * @since Commons IO 1.0
- * @version $Revision: 587978 $ $Date: 2007-10-24 20:36:51 +0100 (Wed, 24 Oct 2007) $
- *
- * @author Stephen Colebourne
- */
-public class TrueFileFilter implements IOFileFilter, Serializable {
-
- /**
- * Singleton instance of true filter.
- * @since Commons IO 1.3
- */
- public static final IOFileFilter TRUE = new TrueFileFilter();
- /**
- * Singleton instance of true filter.
- * Please use the identical TrueFileFilter.TRUE constant.
- * The new name is more JDK 1.5 friendly as it doesn't clash with other
- * values when using static imports.
- */
- public static final IOFileFilter INSTANCE = TRUE;
-
- /**
- * Restrictive consructor.
- */
- protected TrueFileFilter() {
- }
-
- /**
- * Returns true.
- *
- * @param file the file to check
- * @return true
- */
- public boolean accept(File file) {
- return true;
- }
-
- /**
- * Returns true.
- *
- * @param dir the directory to check
- * @param name the filename
- * @return true
- */
- public boolean accept(File dir, String name) {
- return true;
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/WildcardFileFilter.java b/src/org/apache/commons/io/filefilter/WildcardFileFilter.java
deleted file mode 100644
index 791fe985b..000000000
--- a/src/org/apache/commons/io/filefilter/WildcardFileFilter.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.List;
-
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.io.IOCase;
-
-/**
- * Filters files using the supplied wildcards.
- * <p>
- * This filter selects files and directories based on one or more wildcards.
- * Testing is case-sensitive by default, but this can be configured.
- * <p>
- * The wildcard matcher uses the characters '?' and '*' to represent a
- * single or multiple wildcard characters.
- * This is the same as often found on Dos/Unix command lines.
- * The extension check is case-sensitive by .
- * See {@link FilenameUtils#wildcardMatchOnSystem} for more information.
- * <p>
- * For example:
- * <pre>
- * File dir = new File(".");
- * FileFilter fileFilter = new WildcardFileFilter("*test*.java~*~");
- * File[] files = dir.listFiles(fileFilter);
- * for (int i = 0; i < files.length; i++) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * @author Jason Anderson
- * @version $Revision: 155419 $ $Date: 2007-12-22 02:03:16 +0000 (Sat, 22 Dec 2007) $
- * @since Commons IO 1.3
- */
-public class WildcardFileFilter extends AbstractFileFilter implements Serializable {
-
- /** The wildcards that will be used to match filenames. */
- private final String[] wildcards;
- /** Whether the comparison is case sensitive. */
- private final IOCase caseSensitivity;
-
- /**
- * Construct a new case-sensitive wildcard filter for a single wildcard.
- *
- * @param wildcard the wildcard to match
- * @throws IllegalArgumentException if the pattern is null
- */
- public WildcardFileFilter(String wildcard) {
- this(wildcard, null);
- }
-
- /**
- * Construct a new wildcard filter for a single wildcard specifying case-sensitivity.
- *
- * @param wildcard the wildcard to match, not null
- * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the pattern is null
- */
- public WildcardFileFilter(String wildcard, IOCase caseSensitivity) {
- if (wildcard == null) {
- throw new IllegalArgumentException("The wildcard must not be null");
- }
- this.wildcards = new String[] { wildcard };
- this.caseSensitivity = (caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity);
- }
-
- /**
- * Construct a new case-sensitive wildcard filter for an array of wildcards.
- * <p>
- * The array is not cloned, so could be changed after constructing the
- * instance. This would be inadvisable however.
- *
- * @param wildcards the array of wildcards to match
- * @throws IllegalArgumentException if the pattern array is null
- */
- public WildcardFileFilter(String[] wildcards) {
- this(wildcards, null);
- }
-
- /**
- * Construct a new wildcard filter for an array of wildcards specifying case-sensitivity.
- * <p>
- * The array is not cloned, so could be changed after constructing the
- * instance. This would be inadvisable however.
- *
- * @param wildcards the array of wildcards to match, not null
- * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the pattern array is null
- */
- public WildcardFileFilter(String[] wildcards, IOCase caseSensitivity) {
- if (wildcards == null) {
- throw new IllegalArgumentException("The wildcard array must not be null");
- }
- this.wildcards = wildcards;
- this.caseSensitivity = (caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity);
- }
-
- /**
- * Construct a new case-sensitive wildcard filter for a list of wildcards.
- *
- * @param wildcards the list of wildcards to match, not null
- * @throws IllegalArgumentException if the pattern list is null
- * @throws ClassCastException if the list does not contain Strings
- */
- public WildcardFileFilter(List wildcards) {
- this(wildcards, null);
- }
-
- /**
- * Construct a new wildcard filter for a list of wildcards specifying case-sensitivity.
- *
- * @param wildcards the list of wildcards to match, not null
- * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the pattern list is null
- * @throws ClassCastException if the list does not contain Strings
- */
- public WildcardFileFilter(List wildcards, IOCase caseSensitivity) {
- if (wildcards == null) {
- throw new IllegalArgumentException("The wildcard list must not be null");
- }
- this.wildcards = (String[]) wildcards.toArray(new String[wildcards.size()]);
- this.caseSensitivity = (caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Checks to see if the filename matches one of the wildcards.
- *
- * @param dir the file directory
- * @param name the filename
- * @return true if the filename matches one of the wildcards
- */
- public boolean accept(File dir, String name) {
- for (int i = 0; i < wildcards.length; i++) {
- if (FilenameUtils.wildcardMatch(name, wildcards[i], caseSensitivity)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks to see if the filename matches one of the wildcards.
- *
- * @param file the file to check
- * @return true if the filename matches one of the wildcards
- */
- public boolean accept(File file) {
- String name = file.getName();
- for (int i = 0; i < wildcards.length; i++) {
- if (FilenameUtils.wildcardMatch(name, wildcards[i], caseSensitivity)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Provide a String representaion of this file filter.
- *
- * @return a String representaion
- */
- public String toString() {
- StringBuffer buffer = new StringBuffer();
- buffer.append(super.toString());
- buffer.append("(");
- if (wildcards != null) {
- for (int i = 0; i < wildcards.length; i++) {
- if (i > 0) {
- buffer.append(",");
- }
- buffer.append(wildcards[i]);
- }
- }
- buffer.append(")");
- return buffer.toString();
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/WildcardFilter.java b/src/org/apache/commons/io/filefilter/WildcardFilter.java
deleted file mode 100644
index 2a6e0dde0..000000000
--- a/src/org/apache/commons/io/filefilter/WildcardFilter.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.filefilter;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.List;
-
-import org.apache.commons.io.FilenameUtils;
-
-/**
- * Filters files using the supplied wildcards.
- * <p>
- * This filter selects files, but not directories, based on one or more wildcards
- * and using case-sensitive comparison.
- * <p>
- * The wildcard matcher uses the characters '?' and '*' to represent a
- * single or multiple wildcard characters.
- * This is the same as often found on Dos/Unix command lines.
- * The extension check is case-sensitive.
- * See {@link FilenameUtils#wildcardMatch} for more information.
- * <p>
- * For example:
- * <pre>
- * File dir = new File(".");
- * FileFilter fileFilter = new WildcardFilter("*test*.java~*~");
- * File[] files = dir.listFiles(fileFilter);
- * for (int i = 0; i < files.length; i++) {
- * System.out.println(files[i]);
- * }
- * </pre>
- *
- * @author Jason Anderson
- * @version $Revision: 606381 $ $Date: 2007-12-22 02:03:16 +0000 (Sat, 22 Dec 2007) $
- * @since Commons IO 1.1
- * @deprecated Use WilcardFileFilter. Deprecated as this class performs directory
- * filtering which it shouldn't do, but that can't be removed due to compatability.
- */
-public class WildcardFilter extends AbstractFileFilter implements Serializable {
-
- /** The wildcards that will be used to match filenames. */
- private final String[] wildcards;
-
- /**
- * Construct a new case-sensitive wildcard filter for a single wildcard.
- *
- * @param wildcard the wildcard to match
- * @throws IllegalArgumentException if the pattern is null
- */
- public WildcardFilter(String wildcard) {
- if (wildcard == null) {
- throw new IllegalArgumentException("The wildcard must not be null");
- }
- this.wildcards = new String[] { wildcard };
- }
-
- /**
- * Construct a new case-sensitive wildcard filter for an array of wildcards.
- *
- * @param wildcards the array of wildcards to match
- * @throws IllegalArgumentException if the pattern array is null
- */
- public WildcardFilter(String[] wildcards) {
- if (wildcards == null) {
- throw new IllegalArgumentException("The wildcard array must not be null");
- }
- this.wildcards = wildcards;
- }
-
- /**
- * Construct a new case-sensitive wildcard filter for a list of wildcards.
- *
- * @param wildcards the list of wildcards to match
- * @throws IllegalArgumentException if the pattern list is null
- * @throws ClassCastException if the list does not contain Strings
- */
- public WildcardFilter(List wildcards) {
- if (wildcards == null) {
- throw new IllegalArgumentException("The wildcard list must not be null");
- }
- this.wildcards = (String[]) wildcards.toArray(new String[wildcards.size()]);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Checks to see if the filename matches one of the wildcards.
- *
- * @param dir the file directory
- * @param name the filename
- * @return true if the filename matches one of the wildcards
- */
- public boolean accept(File dir, String name) {
- if (dir != null && new File(dir, name).isDirectory()) {
- return false;
- }
-
- for (int i = 0; i < wildcards.length; i++) {
- if (FilenameUtils.wildcardMatch(name, wildcards[i])) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Checks to see if the filename matches one of the wildcards.
- *
- * @param file the file to check
- * @return true if the filename matches one of the wildcards
- */
- public boolean accept(File file) {
- if (file.isDirectory()) {
- return false;
- }
-
- for (int i = 0; i < wildcards.length; i++) {
- if (FilenameUtils.wildcardMatch(file.getName(), wildcards[i])) {
- return true;
- }
- }
-
- return false;
- }
-
-}
diff --git a/src/org/apache/commons/io/filefilter/package.html b/src/org/apache/commons/io/filefilter/package.html
deleted file mode 100644
index 7a45f251d..000000000
--- a/src/org/apache/commons/io/filefilter/package.html
+++ /dev/null
@@ -1,143 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<html>
-<body>
-<p>This package defines an interface (IOFileFilter) that combines both
-{@link java.io.FileFilter} and {@link java.io.FilenameFilter}. Besides
-that the package offers a series of ready-to-use implementations of the
-IOFileFilter interface including implementation that allow you to combine
-other such filters.</p>
-<p>These filter can be used to list files or in {@link java.awt.FileDialog},
-for example.</p>
-
-<p>There are a number of 'primitive' filters:</p>
-
-<table>
- <tbody>
- <tr>
- <td><a href="DirectoryFileFilter.html">DirectoryFilter</a></td>
- <td>Only accept directories</td>
- </tr>
- <tr>
- <td><a href="PrefixFileFilter.html">PrefixFileFilter</a></td>
- <td>Filter based on a prefix</td>
- </tr>
- <tr>
- <td><a href="SuffixFileFilter.html">SuffixFileFilter</a></td>
- <td>Filter based on a suffix</td>
- </tr>
- <tr>
- <td><a href="NameFileFilter.html">NameFileFilter</a></td>
- <td>Filter based on a filename</td>
- </tr>
- <tr>
- <td><a href="WildcardFileFilter.html">WildcardFileFilter</a></td>
- <td>Filter based on wildcards</td>
- </tr>
- <tr>
- <td><a href="AgeFileFilter.html">AgeFileFilter</a></td>
- <td>Filter based on last modified time of file</td>
- </tr>
- <tr>
- <td><a href="SizeFileFilter.html">SizeFileFilter</a></td>
- <td>Filter based on file size</td>
- </tr>
- </tbody>
-</table>
-
-<p>And there are five 'boolean' filters:</p>
-
-<table>
- <tbody>
- <tr>
- <td><a href="TrueFileFilter.html">TrueFileFilter</a></td>
- <td>Accept all files</td>
- </tr>
- <tr>
- <td><a href="FalseFileFilter.html">FalseFileFilter</a></td>
- <td>Accept no files</td>
- </tr>
- <tr>
- <td><a href="NotFileFilter.html">NotFileFilter</a></td>
- <td>Applies a logical NOT to an existing filter</td>
- </tr>
- <tr>
- <td><a href="AndFileFilter.html">AndFileFilter</a></td>
- <td>Combines two filters using a logical AND</td>
- </tr>
- <tr>
- <td><a href="OrFileFilter.html">OrFileFilter</a></td>
- <td>Combines two filter using a logical OR</td>
- </tr>
-
- </tbody>
-</table>
-
-<p>These boolean FilenameFilters can be nested, to allow arbitrary expressions.
-For example, here is how one could print all non-directory files in the
-current directory, starting with "A", and ending in ".java" or ".class":</p>
-
-<pre>
- File dir = new File(".");
- String[] files = dir.list(
- new AndFileFilter(
- new AndFileFilter(
- new PrefixFileFilter("A"),
- new OrFileFilter(
- new SuffixFileFilter(".class"),
- new SuffixFileFilter(".java")
- )
- ),
- new NotFileFilter(
- new DirectoryFileFilter()
- )
- )
- );
- for ( int i=0; i&lt;files.length; i++ ) {
- System.out.println(files[i]);
- }
-</pre>
-
-<p>This package also contains a utility class:
-<a href="FileFilterUtils.html">FileFilterUtils</a>. It allows you to use all
-file filters without having to put them in the import section. Here's how the
-above example will look using FileFilterUtils:</p>
-<pre>
- File dir = new File(".");
- String[] files = dir.list(
- FileFilterUtils.andFileFilter(
- FileFilterUtils.andFileFilter(
- FileFilterUtils.prefixFileFilter("A"),
- FileFilterUtils.orFileFilter(
- FileFilterUtils.suffixFileFilter(".class"),
- FileFilterUtils.suffixFileFilter(".java")
- )
- ),
- FileFilterUtils.notFileFilter(
- FileFilterUtils.directoryFileFilter()
- )
- )
- );
- for ( int i=0; i&lt;files.length; i++ ) {
- System.out.println(files[i]);
- }
-</pre>
-<p>There are a few other goodies in that class so please have a look at the
-documentation in detail.</p>
- </body>
-</html>
diff --git a/src/org/apache/commons/io/input/AutoCloseInputStream.java b/src/org/apache/commons/io/input/AutoCloseInputStream.java
deleted file mode 100644
index bb62358f7..000000000
--- a/src/org/apache/commons/io/input/AutoCloseInputStream.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.input;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Proxy stream that closes and discards the underlying stream as soon as the
- * end of input has been reached or when the stream is explicitly closed.
- * Not even a reference to the underlying stream is kept after it has been
- * closed, so any allocated in-memory buffers can be freed even if the
- * client application still keeps a reference to the proxy stream.
- * <p>
- * This class is typically used to release any resources related to an open
- * stream as soon as possible even if the client application (by not explicitly
- * closing the stream when no longer needed) or the underlying stream (by not
- * releasing resources once the last byte has been read) do not do that.
- *
- * @version $Id: AutoCloseInputStream.java 610010 2008-01-08 14:50:59Z niallp $
- * @since Commons IO 1.4
- */
-public class AutoCloseInputStream extends ProxyInputStream {
-
- /**
- * Creates an automatically closing proxy for the given input stream.
- *
- * @param in underlying input stream
- */
- public AutoCloseInputStream(InputStream in) {
- super(in);
- }
-
- /**
- * Closes the underlying input stream and replaces the reference to it
- * with a {@link ClosedInputStream} instance.
- * <p>
- * This method is automatically called by the read methods when the end
- * of input has been reached.
- * <p>
- * Note that it is safe to call this method any number of times. The original
- * underlying input stream is closed and discarded only once when this
- * method is first called.
- *
- * @throws IOException if the underlying input stream can not be closed
- */
- public void close() throws IOException {
- in.close();
- in = new ClosedInputStream();
- }
-
- /**
- * Reads and returns a single byte from the underlying input stream.
- * If the underlying stream returns -1, the {@link #close()} method is
- * called to automatically close and discard the stream.
- *
- * @return next byte in the stream, or -1 if no more bytes are available
- * @throws IOException if the stream could not be read or closed
- */
- public int read() throws IOException {
- int n = in.read();
- if (n == -1) {
- close();
- }
- return n;
- }
-
- /**
- * Reads and returns bytes from the underlying input stream to the given
- * buffer. If the underlying stream returns -1, the {@link #close()} method
- * i called to automatically close and discard the stream.
- *
- * @param b buffer to which bytes from the stream are written
- * @return number of bytes read, or -1 if no more bytes are available
- * @throws IOException if the stream could not be read or closed
- */
- public int read(byte[] b) throws IOException {
- int n = in.read(b);
- if (n == -1) {
- close();
- }
- return n;
- }
-
- /**
- * Reads and returns bytes from the underlying input stream to the given
- * buffer. If the underlying stream returns -1, the {@link #close()} method
- * i called to automatically close and discard the stream.
- *
- * @param b buffer to which bytes from the stream are written
- * @param off start offset within the buffer
- * @param len maximum number of bytes to read
- * @return number of bytes read, or -1 if no more bytes are available
- * @throws IOException if the stream could not be read or closed
- */
- public int read(byte[] b, int off, int len) throws IOException {
- int n = in.read(b, off, len);
- if (n == -1) {
- close();
- }
- return n;
- }
-
- /**
- * Ensures that the stream is closed before it gets garbage-collected.
- * As mentioned in {@link #close()}, this is a no-op if the stream has
- * already been closed.
- * @throws Throwable if an error occurs
- */
- protected void finalize() throws Throwable {
- close();
- super.finalize();
- }
-
-}
diff --git a/src/org/apache/commons/io/input/CharSequenceReader.java b/src/org/apache/commons/io/input/CharSequenceReader.java
deleted file mode 100644
index 6ee11d87d..000000000
--- a/src/org/apache/commons/io/input/CharSequenceReader.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.input;
-
-import java.io.Reader;
-import java.io.Serializable;
-
-/**
- * {@link Reader} implementation that can read from String, StringBuffer,
- * StringBuilder or CharBuffer.
- * <p>
- * <strong>Note:</strong> Supports {@link #mark(int)} and {@link #reset()}.
- *
- * @version $Revision: 610516 $ $Date: 2008-01-09 19:05:05 +0000 (Wed, 09 Jan 2008) $
- * @since Commons IO 1.4
- */
-public class CharSequenceReader extends Reader implements Serializable {
-
- private final CharSequence charSequence;
- private int idx;
- private int mark;
-
- /**
- * Construct a new instance with the specified character sequence.
- *
- * @param charSequence The character sequence, may be <code>null</code>
- */
- public CharSequenceReader(CharSequence charSequence) {
- this.charSequence = (charSequence != null ? charSequence : "");
- }
-
- /**
- * Close resets the file back to the start and removes any marked position.
- */
- public void close() {
- idx = 0;
- mark = 0;
- }
-
- /**
- * Mark the current position.
- *
- * @param readAheadLimit ignored
- */
- public void mark(int readAheadLimit) {
- mark = idx;
- }
-
- /**
- * Mark is supported (returns true).
- *
- * @return <code>true</code>
- */
- public boolean markSupported() {
- return true;
- }
-
- /**
- * Read a single character.
- *
- * @return the next character from the character sequence
- * or -1 if the end has been reached.
- */
- public int read() {
- if (idx >= charSequence.length()) {
- return -1;
- } else {
- return charSequence.charAt(idx++);
- }
- }
-
- /**
- * Read the sepcified number of characters into the array.
- *
- * @param array The array to store the characters in
- * @param offset The starting position in the array to store
- * @param length The maximum number of characters to read
- * @return The number of characters read or -1 if there are
- * no more
- */
- public int read(char[] array, int offset, int length) {
- if (idx >= charSequence.length()) {
- return -1;
- }
- if (array == null) {
- throw new NullPointerException("Character array is missing");
- }
- if (length < 0 || (offset + length) > array.length) {
- throw new IndexOutOfBoundsException("Array Size=" + array.length +
- ", offset=" + offset + ", length=" + length);
- }
- int count = 0;
- for (int i = 0; i < length; i++) {
- int c = read();
- if (c == -1) {
- return count;
- }
- array[offset + i] = (char)c;
- count++;
- }
- return count;
- }
-
- /**
- * Reset the reader to the last marked position (or the beginning if
- * mark has not been called).
- */
- public void reset() {
- idx = mark;
- }
-
- /**
- * Skip the specified number of characters.
- *
- * @param n The number of characters to skip
- * @return The actual number of characters skipped
- */
- public long skip(long n) {
- if (n < 0) {
- throw new IllegalArgumentException(
- "Number of characters to skip is less than zero: " + n);
- }
- if (idx >= charSequence.length()) {
- return -1;
- }
- int dest = (int)Math.min(charSequence.length(), (idx + n));
- int count = dest - idx;
- idx = dest;
- return count;
- }
-
- /**
- * Return a String representation of the underlying
- * character sequence.
- *
- * @return The contents of the character sequence
- */
- public String toString() {
- return charSequence.toString();
- }
-}
diff --git a/src/org/apache/commons/io/input/ClassLoaderObjectInputStream.java b/src/org/apache/commons/io/input/ClassLoaderObjectInputStream.java
deleted file mode 100644
index 13d048946..000000000
--- a/src/org/apache/commons/io/input/ClassLoaderObjectInputStream.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.input;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectStreamClass;
-import java.io.StreamCorruptedException;
-
-/**
- * A special ObjectInputStream that loads a class based on a specified
- * <code>ClassLoader</code> rather than the system default.
- * <p>
- * This is useful in dynamic container environments.
- *
- * @author Paul Hammant
- * @version $Id: ClassLoaderObjectInputStream.java 437567 2006-08-28 06:39:07Z bayard $
- * @since Commons IO 1.1
- */
-public class ClassLoaderObjectInputStream extends ObjectInputStream {
-
- /** The class loader to use. */
- private ClassLoader classLoader;
-
- /**
- * Constructs a new ClassLoaderObjectInputStream.
- *
- * @param classLoader the ClassLoader from which classes should be loaded
- * @param inputStream the InputStream to work on
- * @throws IOException in case of an I/O error
- * @throws StreamCorruptedException if the stream is corrupted
- */
- public ClassLoaderObjectInputStream(
- ClassLoader classLoader, InputStream inputStream)
- throws IOException, StreamCorruptedException {
- super(inputStream);
- this.classLoader = classLoader;
- }
-
- /**
- * Resolve a class specified by the descriptor using the
- * specified ClassLoader or the super ClassLoader.
- *
- * @param objectStreamClass descriptor of the class
- * @return the Class object described by the ObjectStreamClass
- * @throws IOException in case of an I/O error
- * @throws ClassNotFoundException if the Class cannot be found
- */
- protected Class resolveClass(ObjectStreamClass objectStreamClass)
- throws IOException, ClassNotFoundException {
-
- Class clazz = Class.forName(objectStreamClass.getName(), false, classLoader);
-
- if (clazz != null) {
- // the classloader knows of the class
- return clazz;
- } else {
- // classloader knows not of class, let the super classloader do it
- return super.resolveClass(objectStreamClass);
- }
- }
-}
diff --git a/src/org/apache/commons/io/input/CloseShieldInputStream.java b/src/org/apache/commons/io/input/CloseShieldInputStream.java
deleted file mode 100644
index 2058beeb2..000000000
--- a/src/org/apache/commons/io/input/CloseShieldInputStream.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.input;
-
-import java.io.InputStream;
-
-/**
- * Proxy stream that prevents the underlying input stream from being closed.
- * <p>
- * This class is typically used in cases where an input stream needs to be
- * passed to a component that wants to explicitly close the stream even if
- * more input would still be available to other components.
- *
- * @version $Id: CloseShieldInputStream.java 587913 2007-10-24 15:47:30Z niallp $
- * @since Commons IO 1.4
- */
-public class CloseShieldInputStream extends ProxyInputStream {
-
- /**
- * Creates a proxy that shields the given input stream from being
- * closed.
- *
- * @param in underlying input stream
- */
- public CloseShieldInputStream(InputStream in) {
- super(in);
- }
-
- /**
- * Replaces the underlying input stream with a {@link ClosedInputStream}
- * sentinel. The original input stream will remain open, but this proxy
- * will appear closed.
- */
- public void close() {
- in = new ClosedInputStream();
- }
-
-}
diff --git a/src/org/apache/commons/io/input/ClosedInputStream.java b/src/org/apache/commons/io/input/ClosedInputStream.java
deleted file mode 100644
index 86c83c903..000000000
--- a/src/org/apache/commons/io/input/ClosedInputStream.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.input;
-
-import java.io.InputStream;
-
-/**
- * Closed input stream. This stream returns -1 to all attempts to read
- * something from the stream.
- * <p>
- * Typically uses of this class include testing for corner cases in methods
- * that accept input streams and acting as a sentinel value instead of a
- * <code>null</code> input stream.
- *
- * @version $Id: ClosedInputStream.java 601751 2007-12-06 14:55:45Z niallp $
- * @since Commons IO 1.4
- */
-public class ClosedInputStream extends InputStream {
-
- /**
- * A singleton.
- */
- public static final ClosedInputStream CLOSED_INPUT_STREAM = new ClosedInputStream();
-
- /**
- * Returns -1 to indicate that the stream is closed.
- *
- * @return always -1
- */
- public int read() {
- return -1;
- }
-
-}
diff --git a/src/org/apache/commons/io/input/CountingInputStream.java b/src/org/apache/commons/io/input/CountingInputStream.java
deleted file mode 100644
index 2782276c8..000000000
--- a/src/org/apache/commons/io/input/CountingInputStream.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.input;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * A decorating input stream that counts the number of bytes that have passed
- * through the stream so far.
- * <p>
- * A typical use case would be during debugging, to ensure that data is being
- * read as expected.
- *
- * @author Marcelo Liberato
- * @version $Id: CountingInputStream.java 471628 2006-11-06 04:06:45Z bayard $
- */
-public class CountingInputStream extends ProxyInputStream {
-
- /** The count of bytes that have passed. */
- private long count;
-
- /**
- * Constructs a new CountingInputStream.
- *
- * @param in the InputStream to delegate to
- */
- public CountingInputStream(InputStream in) {
- super(in);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Reads a number of bytes into the byte array, keeping count of the
- * number read.
- *
- * @param b the buffer into which the data is read, not null
- * @return the total number of bytes read into the buffer, -1 if end of stream
- * @throws IOException if an I/O error occurs
- * @see java.io.InputStream#read(byte[])
- */
- public int read(byte[] b) throws IOException {
- int found = super.read(b);
- this.count += (found >= 0) ? found : 0;
- return found;
- }
-
- /**
- * Reads a number of bytes into the byte array at a specific offset,
- * keeping count of the number read.
- *
- * @param b the buffer into which the data is read, not null
- * @param off the start offset in the buffer
- * @param len the maximum number of bytes to read
- * @return the total number of bytes read into the buffer, -1 if end of stream
- * @throws IOException if an I/O error occurs
- * @see java.io.InputStream#read(byte[], int, int)
- */
- public int read(byte[] b, int off, int len) throws IOException {
- int found = super.read(b, off, len);
- this.count += (found >= 0) ? found : 0;
- return found;
- }
-
- /**
- * Reads the next byte of data adding to the count of bytes received
- * if a byte is successfully read.
- *
- * @return the byte read, -1 if end of stream
- * @throws IOException if an I/O error occurs
- * @see java.io.InputStream#read()
- */
- public int read() throws IOException {
- int found = super.read();
- this.count += (found >= 0) ? 1 : 0;
- return found;
- }
-
- /**
- * Skips the stream over the specified number of bytes, adding the skipped
- * amount to the count.
- *
- * @param length the number of bytes to skip
- * @return the actual number of bytes skipped
- * @throws IOException if an I/O error occurs
- * @see java.io.InputStream#skip(long)
- */
- public long skip(final long length) throws IOException {
- final long skip = super.skip(length);
- this.count += skip;
- return skip;
- }
-
- //-----------------------------------------------------------------------
- /**
- * The number of bytes that have passed through this stream.
- * <p>
- * NOTE: From v1.3 this method throws an ArithmeticException if the
- * count is greater than can be expressed by an <code>int</code>.
- * See {@link #getByteCount()} for a method using a <code>long</code>.
- *
- * @return the number of bytes accumulated
- * @throws ArithmeticException if the byte count is too large
- */
- public synchronized int getCount() {
- long result = getByteCount();
- if (result > Integer.MAX_VALUE) {
- throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int");
- }
- return (int) result;
- }
-
- /**
- * Set the byte count back to 0.
- * <p>
- * NOTE: From v1.3 this method throws an ArithmeticException if the
- * count is greater than can be expressed by an <code>int</code>.
- * See {@link #resetByteCount()} for a method using a <code>long</code>.
- *
- * @return the count previous to resetting
- * @throws ArithmeticException if the byte count is too large
- */
- public synchronized int resetCount() {
- long result = resetByteCount();
- if (result > Integer.MAX_VALUE) {
- throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int");
- }
- return (int) result;
- }
-
- /**
- * The number of bytes that have passed through this stream.
- * <p>
- * NOTE: This method is an alternative for <code>getCount()</code>
- * and was added because that method returns an integer which will
- * result in incorrect count for files over 2GB.
- *
- * @return the number of bytes accumulated
- * @since Commons IO 1.3
- */
- public synchronized long getByteCount() {
- return this.count;
- }
-
- /**
- * Set the byte count back to 0.
- * <p>
- * NOTE: This method is an alternative for <code>resetCount()</code>
- * and was added because that method returns an integer which will
- * result in incorrect count for files over 2GB.
- *
- * @return the count previous to resetting
- * @since Commons IO 1.3
- */
- public synchronized long resetByteCount() {
- long tmp = this.count;
- this.count = 0;
- return tmp;
- }
-
-}
diff --git a/src/org/apache/commons/io/input/DemuxInputStream.java b/src/org/apache/commons/io/input/DemuxInputStream.java
deleted file mode 100644
index 1ae888916..000000000
--- a/src/org/apache/commons/io/input/DemuxInputStream.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.input;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Data written to this stream is forwarded to a stream that has been associated
- * with this thread.
- *
- * @author <a href="mailto:peter@apache.org">Peter Donald</a>
- * @version $Revision: 437567 $ $Date: 2006-08-28 07:39:07 +0100 (Mon, 28 Aug 2006) $
- */
-public class DemuxInputStream
- extends InputStream
-{
- private InheritableThreadLocal m_streams = new InheritableThreadLocal();
-
- /**
- * Bind the specified stream to the current thread.
- *
- * @param input the stream to bind
- * @return the InputStream that was previously active
- */
- public InputStream bindStream( InputStream input )
- {
- InputStream oldValue = getStream();
- m_streams.set( input );
- return oldValue;
- }
-
- /**
- * Closes stream associated with current thread.
- *
- * @throws IOException if an error occurs
- */
- public void close()
- throws IOException
- {
- InputStream input = getStream();
- if( null != input )
- {
- input.close();
- }
- }
-
- /**
- * Read byte from stream associated with current thread.
- *
- * @return the byte read from stream
- * @throws IOException if an error occurs
- */
- public int read()
- throws IOException
- {
- InputStream input = getStream();
- if( null != input )
- {
- return input.read();
- }
- else
- {
- return -1;
- }
- }
-
- /**
- * Utility method to retrieve stream bound to current thread (if any).
- *
- * @return the input stream
- */
- private InputStream getStream()
- {
- return (InputStream)m_streams.get();
- }
-}
diff --git a/src/org/apache/commons/io/input/NullInputStream.java b/src/org/apache/commons/io/input/NullInputStream.java
deleted file mode 100644
index 7cee2c6d0..000000000
--- a/src/org/apache/commons/io/input/NullInputStream.java
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.input;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * A functional, light weight {@link InputStream} that emulates
- * a stream of a specified size.
- * <p>
- * This implementation provides a light weight
- * object for testing with an {@link InputStream}
- * where the contents don't matter.
- * <p>
- * One use case would be for testing the handling of
- * large {@link InputStream} as it can emulate that
- * scenario without the overhead of actually processing
- * large numbers of bytes - significantly speeding up
- * test execution times.
- * <p>
- * This implementation returns zero from the method that
- * reads a byte and leaves the array unchanged in the read
- * methods that are passed a byte array.
- * If alternative data is required the <code>processByte()</code> and
- * <code>processBytes()</code> methods can be implemented to generate
- * data, for example:
- *
- * <pre>
- * public class TestInputStream extends NullInputStream {
- * public TestInputStream(int size) {
- * super(size);
- * }
- * protected int processByte() {
- * return ... // return required value here
- * }
- * protected void processBytes(byte[] bytes, int offset, int length) {
- * for (int i = offset; i < length; i++) {
- * bytes[i] = ... // set array value here
- * }
- * }
- * }
- * </pre>
- *
- * @since Commons IO 1.3
- * @version $Revision: 463529 $
- */
-public class NullInputStream extends InputStream {
-
- private long size;
- private long position;
- private long mark = -1;
- private long readlimit;
- private boolean eof;
- private boolean throwEofException;
- private boolean markSupported;
-
- /**
- * Create an {@link InputStream} that emulates a specified size
- * which supports marking and does not throw EOFException.
- *
- * @param size The size of the input stream to emulate.
- */
- public NullInputStream(long size) {
- this(size, true, false);
- }
-
- /**
- * Create an {@link InputStream} that emulates a specified
- * size with option settings.
- *
- * @param size The size of the input stream to emulate.
- * @param markSupported Whether this instance will support
- * the <code>mark()</code> functionality.
- * @param throwEofException Whether this implementation
- * will throw an {@link EOFException} or return -1 when the
- * end of file is reached.
- */
- public NullInputStream(long size, boolean markSupported, boolean throwEofException) {
- this.size = size;
- this.markSupported = markSupported;
- this.throwEofException = throwEofException;
- }
-
- /**
- * Return the current position.
- *
- * @return the current position.
- */
- public long getPosition() {
- return position;
- }
-
- /**
- * Return the size this {@link InputStream} emulates.
- *
- * @return The size of the input stream to emulate.
- */
- public long getSize() {
- return size;
- }
-
- /**
- * Return the number of bytes that can be read.
- *
- * @return The number of bytes that can be read.
- */
- public int available() {
- long avail = size - position;
- if (avail <= 0) {
- return 0;
- } else if (avail > Integer.MAX_VALUE) {
- return Integer.MAX_VALUE;
- } else {
- return (int)avail;
- }
- }
-
- /**
- * Close this input stream - resets the internal state to
- * the initial values.
- *
- * @throws IOException If an error occurs.
- */
- public void close() throws IOException {
- eof = false;
- position = 0;
- mark = -1;
- }
-
- /**
- * Mark the current position.
- *
- * @param readlimit The number of bytes before this marked position
- * is invalid.
- * @throws UnsupportedOperationException if mark is not supported.
- */
- public synchronized void mark(int readlimit) {
- if (!markSupported) {
- throw new UnsupportedOperationException("Mark not supported");
- }
- mark = position;
- this.readlimit = readlimit;
- }
-
- /**
- * Indicates whether <i>mark</i> is supported.
- *
- * @return Whether <i>mark</i> is supported or not.
- */
- public boolean markSupported() {
- return markSupported;
- }
-
- /**
- * Read a byte.
- *
- * @return Either The byte value returned by <code>processByte()</code>
- * or <code>-1</code> if the end of file has been reached and
- * <code>throwEofException</code> is set to <code>false</code>.
- * @throws EOFException if the end of file is reached and
- * <code>throwEofException</code> is set to <code>true</code>.
- * @throws IOException if trying to read past the end of file.
- */
- public int read() throws IOException {
- if (eof) {
- throw new IOException("Read after end of file");
- }
- if (position == size) {
- return doEndOfFile();
- }
- position++;
- return processByte();
- }
-
- /**
- * Read some bytes into the specified array.
- *
- * @param bytes The byte array to read into
- * @return The number of bytes read or <code>-1</code>
- * if the end of file has been reached and
- * <code>throwEofException</code> is set to <code>false</code>.
- * @throws EOFException if the end of file is reached and
- * <code>throwEofException</code> is set to <code>true</code>.
- * @throws IOException if trying to read past the end of file.
- */
- public int read(byte[] bytes) throws IOException {
- return read(bytes, 0, bytes.length);
- }
-
- /**
- * Read the specified number bytes into an array.
- *
- * @param bytes The byte array to read into.
- * @param offset The offset to start reading bytes into.
- * @param length The number of bytes to read.
- * @return The number of bytes read or <code>-1</code>
- * if the end of file has been reached and
- * <code>throwEofException</code> is set to <code>false</code>.
- * @throws EOFException if the end of file is reached and
- * <code>throwEofException</code> is set to <code>true</code>.
- * @throws IOException if trying to read past the end of file.
- */
- public int read(byte[] bytes, int offset, int length) throws IOException {
- if (eof) {
- throw new IOException("Read after end of file");
- }
- if (position == size) {
- return doEndOfFile();
- }
- position += length;
- int returnLength = length;
- if (position > size) {
- returnLength = length - (int)(position - size);
- position = size;
- }
- processBytes(bytes, offset, returnLength);
- return returnLength;
- }
-
- /**
- * Reset the stream to the point when mark was last called.
- *
- * @throws UnsupportedOperationException if mark is not supported.
- * @throws IOException If no position has been marked
- * or the read limit has been exceed since the last position was
- * marked.
- */
- public synchronized void reset() throws IOException {
- if (!markSupported) {
- throw new UnsupportedOperationException("Mark not supported");
- }
- if (mark < 0) {
- throw new IOException("No position has been marked");
- }
- if (position > (mark + readlimit)) {
- throw new IOException("Marked position [" + mark +
- "] is no longer valid - passed the read limit [" +
- readlimit + "]");
- }
- position = mark;
- eof = false;
- }
-
- /**
- * Skip a specified number of bytes.
- *
- * @param numberOfBytes The number of bytes to skip.
- * @return The number of bytes skipped or <code>-1</code>
- * if the end of file has been reached and
- * <code>throwEofException</code> is set to <code>false</code>.
- * @throws EOFException if the end of file is reached and
- * <code>throwEofException</code> is set to <code>true</code>.
- * @throws IOException if trying to read past the end of file.
- */
- public long skip(long numberOfBytes) throws IOException {
- if (eof) {
- throw new IOException("Skip after end of file");
- }
- if (position == size) {
- return doEndOfFile();
- }
- position += numberOfBytes;
- long returnLength = numberOfBytes;
- if (position > size) {
- returnLength = numberOfBytes - (position - size);
- position = size;
- }
- return returnLength;
- }
-
- /**
- * Return a byte value for the <code>read()</code> method.
- * <p>
- * This implementation returns zero.
- *
- * @return This implementation always returns zero.
- */
- protected int processByte() {
- // do nothing - overridable by subclass
- return 0;
- }
-
- /**
- * Process the bytes for the <code>read(byte[], offset, length)</code>
- * method.
- * <p>
- * This implementation leaves the byte array unchanged.
- *
- * @param bytes The byte array
- * @param offset The offset to start at.
- * @param length The number of bytes.
- */
- protected void processBytes(byte[] bytes, int offset, int length) {
- // do nothing - overridable by subclass
- }
-
- /**
- * Handle End of File.
- *
- * @return <code>-1</code> if <code>throwEofException</code> is
- * set to <code>false</code>
- * @throws EOFException if <code>throwEofException</code> is set
- * to <code>true</code>.
- */
- private int doEndOfFile() throws EOFException {
- eof = true;
- if (throwEofException) {
- throw new EOFException();
- }
- return -1;
- }
-
-}
diff --git a/src/org/apache/commons/io/input/NullReader.java b/src/org/apache/commons/io/input/NullReader.java
deleted file mode 100644
index 159e39021..000000000
--- a/src/org/apache/commons/io/input/NullReader.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.input;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.Reader;
-
-/**
- * A functional, light weight {@link Reader} that emulates
- * a reader of a specified size.
- * <p>
- * This implementation provides a light weight
- * object for testing with an {@link Reader}
- * where the contents don't matter.
- * <p>
- * One use case would be for testing the handling of
- * large {@link Reader} as it can emulate that
- * scenario without the overhead of actually processing
- * large numbers of characters - significantly speeding up
- * test execution times.
- * <p>
- * This implementation returns a space from the method that
- * reads a character and leaves the array unchanged in the read
- * methods that are passed a character array.
- * If alternative data is required the <code>processChar()</code> and
- * <code>processChars()</code> methods can be implemented to generate
- * data, for example:
- *
- * <pre>
- * public class TestReader extends NullReader {
- * public TestReader(int size) {
- * super(size);
- * }
- * protected char processChar() {
- * return ... // return required value here
- * }
- * protected void processChars(char[] chars, int offset, int length) {
- * for (int i = offset; i < length; i++) {
- * chars[i] = ... // set array value here
- * }
- * }
- * }
- * </pre>
- *
- * @since Commons IO 1.3
- * @version $Revision: 463529 $
- */
-public class NullReader extends Reader {
-
- private long size;
- private long position;
- private long mark = -1;
- private long readlimit;
- private boolean eof;
- private boolean throwEofException;
- private boolean markSupported;
-
- /**
- * Create a {@link Reader} that emulates a specified size
- * which supports marking and does not throw EOFException.
- *
- * @param size The size of the reader to emulate.
- */
- public NullReader(long size) {
- this(size, true, false);
- }
-
- /**
- * Create a {@link Reader} that emulates a specified
- * size with option settings.
- *
- * @param size The size of the reader to emulate.
- * @param markSupported Whether this instance will support
- * the <code>mark()</code> functionality.
- * @param throwEofException Whether this implementation
- * will throw an {@link EOFException} or return -1 when the
- * end of file is reached.
- */
- public NullReader(long size, boolean markSupported, boolean throwEofException) {
- this.size = size;
- this.markSupported = markSupported;
- this.throwEofException = throwEofException;
- }
-
- /**
- * Return the current position.
- *
- * @return the current position.
- */
- public long getPosition() {
- return position;
- }
-
- /**
- * Return the size this {@link Reader} emulates.
- *
- * @return The size of the reader to emulate.
- */
- public long getSize() {
- return size;
- }
-
- /**
- * Close this Reader - resets the internal state to
- * the initial values.
- *
- * @throws IOException If an error occurs.
- */
- public void close() throws IOException {
- eof = false;
- position = 0;
- mark = -1;
- }
-
- /**
- * Mark the current position.
- *
- * @param readlimit The number of characters before this marked position
- * is invalid.
- * @throws UnsupportedOperationException if mark is not supported.
- */
- public synchronized void mark(int readlimit) {
- if (!markSupported) {
- throw new UnsupportedOperationException("Mark not supported");
- }
- mark = position;
- this.readlimit = readlimit;
- }
-
- /**
- * Indicates whether <i>mark</i> is supported.
- *
- * @return Whether <i>mark</i> is supported or not.
- */
- public boolean markSupported() {
- return markSupported;
- }
-
- /**
- * Read a character.
- *
- * @return Either The character value returned by <code>processChar()</code>
- * or <code>-1</code> if the end of file has been reached and
- * <code>throwEofException</code> is set to <code>false</code>.
- * @throws EOFException if the end of file is reached and
- * <code>throwEofException</code> is set to <code>true</code>.
- * @throws IOException if trying to read past the end of file.
- */
- public int read() throws IOException {
- if (eof) {
- throw new IOException("Read after end of file");
- }
- if (position == size) {
- return doEndOfFile();
- }
- position++;
- return processChar();
- }
-
- /**
- * Read some characters into the specified array.
- *
- * @param chars The character array to read into
- * @return The number of characters read or <code>-1</code>
- * if the end of file has been reached and
- * <code>throwEofException</code> is set to <code>false</code>.
- * @throws EOFException if the end of file is reached and
- * <code>throwEofException</code> is set to <code>true</code>.
- * @throws IOException if trying to read past the end of file.
- */
- public int read(char[] chars) throws IOException {
- return read(chars, 0, chars.length);
- }
-
- /**
- * Read the specified number characters into an array.
- *
- * @param chars The character array to read into.
- * @param offset The offset to start reading characters into.
- * @param length The number of characters to read.
- * @return The number of characters read or <code>-1</code>
- * if the end of file has been reached and
- * <code>throwEofException</code> is set to <code>false</code>.
- * @throws EOFException if the end of file is reached and
- * <code>throwEofException</code> is set to <code>true</code>.
- * @throws IOException if trying to read past the end of file.
- */
- public int read(char[] chars, int offset, int length) throws IOException {
- if (eof) {
- throw new IOException("Read after end of file");
- }
- if (position == size) {
- return doEndOfFile();
- }
- position += length;
- int returnLength = length;
- if (position > size) {
- returnLength = length - (int)(position - size);
- position = size;
- }
- processChars(chars, offset, returnLength);
- return returnLength;
- }
-
- /**
- * Reset the stream to the point when mark was last called.
- *
- * @throws UnsupportedOperationException if mark is not supported.
- * @throws IOException If no position has been marked
- * or the read limit has been exceed since the last position was
- * marked.
- */
- public synchronized void reset() throws IOException {
- if (!markSupported) {
- throw new UnsupportedOperationException("Mark not supported");
- }
- if (mark < 0) {
- throw new IOException("No position has been marked");
- }
- if (position > (mark + readlimit)) {
- throw new IOException("Marked position [" + mark +
- "] is no longer valid - passed the read limit [" +
- readlimit + "]");
- }
- position = mark;
- eof = false;
- }
-
- /**
- * Skip a specified number of characters.
- *
- * @param numberOfChars The number of characters to skip.
- * @return The number of characters skipped or <code>-1</code>
- * if the end of file has been reached and
- * <code>throwEofException</code> is set to <code>false</code>.
- * @throws EOFException if the end of file is reached and
- * <code>throwEofException</code> is set to <code>true</code>.
- * @throws IOException if trying to read past the end of file.
- */
- public long skip(long numberOfChars) throws IOException {
- if (eof) {
- throw new IOException("Skip after end of file");
- }
- if (position == size) {
- return doEndOfFile();
- }
- position += numberOfChars;
- long returnLength = numberOfChars;
- if (position > size) {
- returnLength = numberOfChars - (position - size);
- position = size;
- }
- return returnLength;
- }
-
- /**
- * Return a character value for the <code>read()</code> method.
- * <p>
- * This implementation returns zero.
- *
- * @return This implementation always returns zero.
- */
- protected int processChar() {
- // do nothing - overridable by subclass
- return 0;
- }
-
- /**
- * Process the characters for the <code>read(char[], offset, length)</code>
- * method.
- * <p>
- * This implementation leaves the character array unchanged.
- *
- * @param chars The character array
- * @param offset The offset to start at.
- * @param length The number of characters.
- */
- protected void processChars(char[] chars, int offset, int length) {
- // do nothing - overridable by subclass
- }
-
- /**
- * Handle End of File.
- *
- * @return <code>-1</code> if <code>throwEofException</code> is
- * set to <code>false</code>
- * @throws EOFException if <code>throwEofException</code> is set
- * to <code>true</code>.
- */
- private int doEndOfFile() throws EOFException {
- eof = true;
- if (throwEofException) {
- throw new EOFException();
- }
- return -1;
- }
-
-}
diff --git a/src/org/apache/commons/io/input/ProxyInputStream.java b/src/org/apache/commons/io/input/ProxyInputStream.java
deleted file mode 100644
index a08ad92d0..000000000
--- a/src/org/apache/commons/io/input/ProxyInputStream.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.input;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * A Proxy stream which acts as expected, that is it passes the method
- * calls on to the proxied stream and doesn't change which methods are
- * being called.
- * <p>
- * It is an alternative base class to FilterInputStream
- * to increase reusability, because FilterInputStream changes the
- * methods being called, such as read(byte[]) to read(byte[], int, int).
- *
- * @author Stephen Colebourne
- * @version $Id: ProxyInputStream.java 610010 2008-01-08 14:50:59Z niallp $
- */
-public abstract class ProxyInputStream extends FilterInputStream {
-
- /**
- * Constructs a new ProxyInputStream.
- *
- * @param proxy the InputStream to delegate to
- */
- public ProxyInputStream(InputStream proxy) {
- super(proxy);
- // the proxy is stored in a protected superclass variable named 'in'
- }
-
- /**
- * Invokes the delegate's <code>read()</code> method.
- * @return the byte read or -1 if the end of stream
- * @throws IOException if an I/O error occurs
- */
- public int read() throws IOException {
- return in.read();
- }
-
- /**
- * Invokes the delegate's <code>read(byte[])</code> method.
- * @param bts the buffer to read the bytes into
- * @return the number of bytes read or -1 if the end of stream
- * @throws IOException if an I/O error occurs
- */
- public int read(byte[] bts) throws IOException {
- return in.read(bts);
- }
-
- /**
- * Invokes the delegate's <code>read(byte[], int, int)</code> method.
- * @param bts the buffer to read the bytes into
- * @param st The start offset
- * @param end The number of bytes to read
- * @return the number of bytes read or -1 if the end of stream
- * @throws IOException if an I/O error occurs
- */
- public int read(byte[] bts, int st, int end) throws IOException {
- return in.read(bts, st, end);
- }
-
- /**
- * Invokes the delegate's <code>skip(long)</code> method.
- * @param ln the number of bytes to skip
- * @return the number of bytes to skipped or -1 if the end of stream
- * @throws IOException if an I/O error occurs
- */
- public long skip(long ln) throws IOException {
- return in.skip(ln);
- }
-
- /**
- * Invokes the delegate's <code>available()</code> method.
- * @return the number of available bytes
- * @throws IOException if an I/O error occurs
- */
- public int available() throws IOException {
- return in.available();
- }
-
- /**
- * Invokes the delegate's <code>close()</code> method.
- * @throws IOException if an I/O error occurs
- */
- public void close() throws IOException {
- in.close();
- }
-
- /**
- * Invokes the delegate's <code>mark(int)</code> method.
- * @param idx read ahead limit
- */
- public synchronized void mark(int idx) {
- in.mark(idx);
- }
-
- /**
- * Invokes the delegate's <code>reset()</code> method.
- * @throws IOException if an I/O error occurs
- */
- public synchronized void reset() throws IOException {
- in.reset();
- }
-
- /**
- * Invokes the delegate's <code>markSupported()</code> method.
- * @return true if mark is supported, otherwise false
- */
- public boolean markSupported() {
- return in.markSupported();
- }
-
-}
diff --git a/src/org/apache/commons/io/input/ProxyReader.java b/src/org/apache/commons/io/input/ProxyReader.java
deleted file mode 100644
index d55290f5a..000000000
--- a/src/org/apache/commons/io/input/ProxyReader.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.input;
-
-import java.io.FilterReader;
-import java.io.IOException;
-import java.io.Reader;
-
-/**
- * A Proxy stream which acts as expected, that is it passes the method
- * calls on to the proxied stream and doesn't change which methods are
- * being called.
- * <p>
- * It is an alternative base class to FilterReader
- * to increase reusability, because FilterReader changes the
- * methods being called, such as read(char[]) to read(char[], int, int).
- *
- * @author Stephen Colebourne
- * @version $Id: ProxyReader.java 610010 2008-01-08 14:50:59Z niallp $
- */
-public abstract class ProxyReader extends FilterReader {
-
- /**
- * Constructs a new ProxyReader.
- *
- * @param proxy the Reader to delegate to
- */
- public ProxyReader(Reader proxy) {
- super(proxy);
- // the proxy is stored in a protected superclass variable named 'in'
- }
-
- /**
- * Invokes the delegate's <code>read()</code> method.
- * @return the character read or -1 if the end of stream
- * @throws IOException if an I/O error occurs
- */
- public int read() throws IOException {
- return in.read();
- }
-
- /**
- * Invokes the delegate's <code>read(char[])</code> method.
- * @param chr the buffer to read the characters into
- * @return the number of characters read or -1 if the end of stream
- * @throws IOException if an I/O error occurs
- */
- public int read(char[] chr) throws IOException {
- return in.read(chr);
- }
-
- /**
- * Invokes the delegate's <code>read(char[], int, int)</code> method.
- * @param chr the buffer to read the characters into
- * @param st The start offset
- * @param end The number of bytes to read
- * @return the number of characters read or -1 if the end of stream
- * @throws IOException if an I/O error occurs
- */
- public int read(char[] chr, int st, int end) throws IOException {
- return in.read(chr, st, end);
- }
-
- /**
- * Invokes the delegate's <code>skip(long)</code> method.
- * @param ln the number of bytes to skip
- * @return the number of bytes to skipped or -1 if the end of stream
- * @throws IOException if an I/O error occurs
- */
- public long skip(long ln) throws IOException {
- return in.skip(ln);
- }
-
- /**
- * Invokes the delegate's <code>ready()</code> method.
- * @return true if the stream is ready to be read
- * @throws IOException if an I/O error occurs
- */
- public boolean ready() throws IOException {
- return in.ready();
- }
-
- /**
- * Invokes the delegate's <code>close()</code> method.
- * @throws IOException if an I/O error occurs
- */
- public void close() throws IOException {
- in.close();
- }
-
- /**
- * Invokes the delegate's <code>mark(int)</code> method.
- * @param idx read ahead limit
- * @throws IOException if an I/O error occurs
- */
- public synchronized void mark(int idx) throws IOException {
- in.mark(idx);
- }
-
- /**
- * Invokes the delegate's <code>reset()</code> method.
- * @throws IOException if an I/O error occurs
- */
- public synchronized void reset() throws IOException {
- in.reset();
- }
-
- /**
- * Invokes the delegate's <code>markSupported()</code> method.
- * @return true if mark is supported, otherwise false
- */
- public boolean markSupported() {
- return in.markSupported();
- }
-
-}
diff --git a/src/org/apache/commons/io/input/SwappedDataInputStream.java b/src/org/apache/commons/io/input/SwappedDataInputStream.java
deleted file mode 100644
index 5b65b1eee..000000000
--- a/src/org/apache/commons/io/input/SwappedDataInputStream.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.input;
-
-import java.io.DataInput;
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.commons.io.EndianUtils;
-
-/**
- * DataInput for systems relying on little endian data formats.
- * When read, values will be changed from little endian to big
- * endian formats for internal usage.
- * <p>
- * <b>Origin of code: </b>Avalon Excalibur (IO)
- *
- * @author <a href="mailto:peter@apache.org">Peter Donald</a>
- * @version CVS $Revision: 610010 $ $Date: 2008-01-08 14:50:59 +0000 (Tue, 08 Jan 2008) $
- */
-public class SwappedDataInputStream extends ProxyInputStream
- implements DataInput
-{
-
- /**
- * Constructs a SwappedDataInputStream.
- *
- * @param input InputStream to read from
- */
- public SwappedDataInputStream( InputStream input )
- {
- super( input );
- }
-
- /**
- * Return <code>{@link #readByte()} == 0</code>
- * @return the true if the byte read is zero, otherwise false
- * @throws IOException if an I/O error occurs
- * @throws EOFException if an end of file is reached unexpectedly
- */
- public boolean readBoolean()
- throws IOException, EOFException
- {
- return ( 0 == readByte() );
- }
-
- /**
- * Invokes the delegate's <code>read()</code> method.
- * @return the byte read or -1 if the end of stream
- * @throws IOException if an I/O error occurs
- * @throws EOFException if an end of file is reached unexpectedly
- */
- public byte readByte()
- throws IOException, EOFException
- {
- return (byte)in.read();
- }
-
- /**
- * Reads a character delegating to {@link #readShort()}.
- * @return the byte read or -1 if the end of stream
- * @throws IOException if an I/O error occurs
- * @throws EOFException if an end of file is reached unexpectedly
- */
- public char readChar()
- throws IOException, EOFException
- {
- return (char)readShort();
- }
-
- /**
- * Delegates to {@link EndianUtils#readSwappedDouble(InputStream)}.
- * @return the read long
- * @throws IOException if an I/O error occurs
- * @throws EOFException if an end of file is reached unexpectedly
- */
- public double readDouble()
- throws IOException, EOFException
- {
- return EndianUtils.readSwappedDouble( in );
- }
-
- /**
- * Delegates to {@link EndianUtils#readSwappedFloat(InputStream)}.
- * @return the read long
- * @throws IOException if an I/O error occurs
- * @throws EOFException if an end of file is reached unexpectedly
- */
- public float readFloat()
- throws IOException, EOFException
- {
- return EndianUtils.readSwappedFloat( in );
- }
-
- /**
- * Invokes the delegate's <code>read(byte[] data, int, int)</code> method.
- *
- * @param data the buffer to read the bytes into
- * @throws EOFException if an end of file is reached unexpectedly
- * @throws IOException if an I/O error occurs
- */
- public void readFully( byte[] data )
- throws IOException, EOFException
- {
- readFully( data, 0, data.length );
- }
-
-
- /**
- * Invokes the delegate's <code>read(byte[] data, int, int)</code> method.
- *
- * @param data the buffer to read the bytes into
- * @param offset The start offset
- * @param length The number of bytes to read
- * @throws EOFException if an end of file is reached unexpectedly
- * @throws IOException if an I/O error occurs
- */
- public void readFully( byte[] data, int offset, int length )
- throws IOException, EOFException
- {
- int remaining = length;
-
- while( remaining > 0 )
- {
- int location = offset + ( length - remaining );
- int count = read( data, location, remaining );
-
- if( -1 == count )
- {
- throw new EOFException();
- }
-
- remaining -= count;
- }
- }
-
- /**
- * Delegates to {@link EndianUtils#readSwappedInteger(InputStream)}.
- * @return the read long
- * @throws EOFException if an end of file is reached unexpectedly
- * @throws IOException if an I/O error occurs
- */
- public int readInt()
- throws IOException, EOFException
- {
- return EndianUtils.readSwappedInteger( in );
- }
-
- /**
- * Not currently supported - throws {@link UnsupportedOperationException}.
- * @return the line read
- * @throws EOFException if an end of file is reached unexpectedly
- * @throws IOException if an I/O error occurs
- */
- public String readLine()
- throws IOException, EOFException
- {
- throw new UnsupportedOperationException(
- "Operation not supported: readLine()" );
- }
-
- /**
- * Delegates to {@link EndianUtils#readSwappedLong(InputStream)}.
- * @return the read long
- * @throws EOFException if an end of file is reached unexpectedly
- * @throws IOException if an I/O error occurs
- */
- public long readLong()
- throws IOException, EOFException
- {
- return EndianUtils.readSwappedLong( in );
- }
-
- /**
- * Delegates to {@link EndianUtils#readSwappedShort(InputStream)}.
- * @return the read long
- * @throws EOFException if an end of file is reached unexpectedly
- * @throws IOException if an I/O error occurs
- */
- public short readShort()
- throws IOException, EOFException
- {
- return EndianUtils.readSwappedShort( in );
- }
-
- /**
- * Invokes the delegate's <code>read()</code> method.
- * @return the byte read or -1 if the end of stream
- * @throws EOFException if an end of file is reached unexpectedly
- * @throws IOException if an I/O error occurs
- */
- public int readUnsignedByte()
- throws IOException, EOFException
- {
- return in.read();
- }
-
- /**
- * Delegates to {@link EndianUtils#readSwappedUnsignedShort(InputStream)}.
- * @return the read long
- * @throws EOFException if an end of file is reached unexpectedly
- * @throws IOException if an I/O error occurs
- */
- public int readUnsignedShort()
- throws IOException, EOFException
- {
- return EndianUtils.readSwappedUnsignedShort( in );
- }
-
- /**
- * Not currently supported - throws {@link UnsupportedOperationException}.
- * @return UTF String read
- * @throws EOFException if an end of file is reached unexpectedly
- * @throws IOException if an I/O error occurs
- */
- public String readUTF()
- throws IOException, EOFException
- {
- throw new UnsupportedOperationException(
- "Operation not supported: readUTF()" );
- }
-
- /**
- * Invokes the delegate's <code>skip(int)</code> method.
- * @param count the number of bytes to skip
- * @return the number of bytes to skipped or -1 if the end of stream
- * @throws EOFException if an end of file is reached unexpectedly
- * @throws IOException if an I/O error occurs
- */
- public int skipBytes( int count )
- throws IOException, EOFException
- {
- return (int)in.skip( count );
- }
-
-}
diff --git a/src/org/apache/commons/io/input/TeeInputStream.java b/src/org/apache/commons/io/input/TeeInputStream.java
deleted file mode 100644
index fed000ed6..000000000
--- a/src/org/apache/commons/io/input/TeeInputStream.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.input;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * InputStream proxy that transparently writes a copy of all bytes read
- * from the proxied stream to a given OutputStream. Using {@link #skip(long)}
- * or {@link #mark(int)}/{@link #reset()} on the stream will result on some
- * bytes from the input stream being skipped or duplicated in the output
- * stream.
- * <p>
- * The proxied input stream is closed when the {@link #close()} method is
- * called on this proxy. It is configurable whether the associated output
- * stream will also closed.
- *
- * @version $Id: TeeInputStream.java 587913 2007-10-24 15:47:30Z niallp $
- * @since Commons IO 1.4
- */
-public class TeeInputStream extends ProxyInputStream {
-
- /**
- * The output stream that will receive a copy of all bytes read from the
- * proxied input stream.
- */
- private final OutputStream branch;
-
- /**
- * Flag for closing also the associated output stream when this
- * stream is closed.
- */
- private final boolean closeBranch;
-
- /**
- * Creates a TeeInputStream that proxies the given {@link InputStream}
- * and copies all read bytes to the given {@link OutputStream}. The given
- * output stream will not be closed when this stream gets closed.
- *
- * @param input input stream to be proxied
- * @param branch output stream that will receive a copy of all bytes read
- */
- public TeeInputStream(InputStream input, OutputStream branch) {
- this(input, branch, false);
- }
-
- /**
- * Creates a TeeInputStream that proxies the given {@link InputStream}
- * and copies all read bytes to the given {@link OutputStream}. The given
- * output stream will be closed when this stream gets closed if the
- * closeBranch parameter is <code>true</code>.
- *
- * @param input input stream to be proxied
- * @param branch output stream that will receive a copy of all bytes read
- * @param closeBranch flag for closing also the output stream when this
- * stream is closed
- */
- public TeeInputStream(
- InputStream input, OutputStream branch, boolean closeBranch) {
- super(input);
- this.branch = branch;
- this.closeBranch = closeBranch;
- }
-
- /**
- * Closes the proxied input stream and, if so configured, the associated
- * output stream. An exception thrown from one stream will not prevent
- * closing of the other stream.
- *
- * @throws IOException if either of the streams could not be closed
- */
- public void close() throws IOException {
- try {
- super.close();
- } finally {
- if (closeBranch) {
- branch.close();
- }
- }
- }
-
- /**
- * Reads a single byte from the proxied input stream and writes it to
- * the associated output stream.
- *
- * @return next byte from the stream, or -1 if the stream has ended
- * @throws IOException if the stream could not be read (or written)
- */
- public int read() throws IOException {
- int ch = super.read();
- if (ch != -1) {
- branch.write(ch);
- }
- return ch;
- }
-
- /**
- * Reads bytes from the proxied input stream and writes the read bytes
- * to the associated output stream.
- *
- * @param bts byte buffer
- * @param st start offset within the buffer
- * @param end maximum number of bytes to read
- * @return number of bytes read, or -1 if the stream has ended
- * @throws IOException if the stream could not be read (or written)
- */
- public int read(byte[] bts, int st, int end) throws IOException {
- int n = super.read(bts, st, end);
- if (n != -1) {
- branch.write(bts, st, n);
- }
- return n;
- }
-
- /**
- * Reads bytes from the proxied input stream and writes the read bytes
- * to the associated output stream.
- *
- * @param bts byte buffer
- * @return number of bytes read, or -1 if the stream has ended
- * @throws IOException if the stream could not be read (or written)
- */
- public int read(byte[] bts) throws IOException {
- int n = super.read(bts);
- if (n != -1) {
- branch.write(bts, 0, n);
- }
- return n;
- }
-
-}
diff --git a/src/org/apache/commons/io/input/package.html b/src/org/apache/commons/io/input/package.html
deleted file mode 100644
index 9aa8b15ba..000000000
--- a/src/org/apache/commons/io/input/package.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<html>
-<body>
-<p>
-This package provides implementations of input classes, such as
-<code>InputStream</code> and <code>Reader</code>.
-</p>
-</body>
-</html>
diff --git a/src/org/apache/commons/io/output/ByteArrayOutputStream.java b/src/org/apache/commons/io/output/ByteArrayOutputStream.java
deleted file mode 100644
index 66d5e8dc3..000000000
--- a/src/org/apache/commons/io/output/ByteArrayOutputStream.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.output;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This class implements an output stream in which the data is
- * written into a byte array. The buffer automatically grows as data
- * is written to it.
- * <p>
- * The data can be retrieved using <code>toByteArray()</code> and
- * <code>toString()</code>.
- * <p>
- * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
- * this class can be called after the stream has been closed without
- * generating an <tt>IOException</tt>.
- * <p>
- * This is an alternative implementation of the java.io.ByteArrayOutputStream
- * class. The original implementation only allocates 32 bytes at the beginning.
- * As this class is designed for heavy duty it starts at 1024 bytes. In contrast
- * to the original it doesn't reallocate the whole memory block but allocates
- * additional buffers. This way no buffers need to be garbage collected and
- * the contents don't have to be copied to the new buffer. This class is
- * designed to behave exactly like the original. The only exception is the
- * deprecated toString(int) method that has been ignored.
- *
- * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
- * @author Holger Hoffstatte
- * @version $Id: ByteArrayOutputStream.java 610010 2008-01-08 14:50:59Z niallp $
- */
-public class ByteArrayOutputStream extends OutputStream {
-
- /** A singleton empty byte array. */
- private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
-
- /** The list of buffers, which grows and never reduces. */
- private List buffers = new ArrayList();
- /** The index of the current buffer. */
- private int currentBufferIndex;
- /** The total count of bytes in all the filled buffers. */
- private int filledBufferSum;
- /** The current buffer. */
- private byte[] currentBuffer;
- /** The total count of bytes written. */
- private int count;
-
- /**
- * Creates a new byte array output stream. The buffer capacity is
- * initially 1024 bytes, though its size increases if necessary.
- */
- public ByteArrayOutputStream() {
- this(1024);
- }
-
- /**
- * Creates a new byte array output stream, with a buffer capacity of
- * the specified size, in bytes.
- *
- * @param size the initial size
- * @throws IllegalArgumentException if size is negative
- */
- public ByteArrayOutputStream(int size) {
- if (size < 0) {
- throw new IllegalArgumentException(
- "Negative initial size: " + size);
- }
- needNewBuffer(size);
- }
-
- /**
- * Return the appropriate <code>byte[]</code> buffer
- * specified by index.
- *
- * @param index the index of the buffer required
- * @return the buffer
- */
- private byte[] getBuffer(int index) {
- return (byte[]) buffers.get(index);
- }
-
- /**
- * Makes a new buffer available either by allocating
- * a new one or re-cycling an existing one.
- *
- * @param newcount the size of the buffer if one is created
- */
- private void needNewBuffer(int newcount) {
- if (currentBufferIndex < buffers.size() - 1) {
- //Recycling old buffer
- filledBufferSum += currentBuffer.length;
-
- currentBufferIndex++;
- currentBuffer = getBuffer(currentBufferIndex);
- } else {
- //Creating new buffer
- int newBufferSize;
- if (currentBuffer == null) {
- newBufferSize = newcount;
- filledBufferSum = 0;
- } else {
- newBufferSize = Math.max(
- currentBuffer.length << 1,
- newcount - filledBufferSum);
- filledBufferSum += currentBuffer.length;
- }
-
- currentBufferIndex++;
- currentBuffer = new byte[newBufferSize];
- buffers.add(currentBuffer);
- }
- }
-
- /**
- * Write the bytes to byte array.
- * @param b the bytes to write
- * @param off The start offset
- * @param len The number of bytes to write
- */
- public void write(byte[] b, int off, int len) {
- if ((off < 0)
- || (off > b.length)
- || (len < 0)
- || ((off + len) > b.length)
- || ((off + len) < 0)) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return;
- }
- synchronized (this) {
- int newcount = count + len;
- int remaining = len;
- int inBufferPos = count - filledBufferSum;
- while (remaining > 0) {
- int part = Math.min(remaining, currentBuffer.length - inBufferPos);
- System.arraycopy(b, off + len - remaining, currentBuffer, inBufferPos, part);
- remaining -= part;
- if (remaining > 0) {
- needNewBuffer(newcount);
- inBufferPos = 0;
- }
- }
- count = newcount;
- }
- }
-
- /**
- * Write a byte to byte array.
- * @param b the byte to write
- */
- public synchronized void write(int b) {
- int inBufferPos = count - filledBufferSum;
- if (inBufferPos == currentBuffer.length) {
- needNewBuffer(count + 1);
- inBufferPos = 0;
- }
- currentBuffer[inBufferPos] = (byte) b;
- count++;
- }
-
- /**
- * Writes the entire contents of the specified input stream to this
- * byte stream. Bytes from the input stream are read directly into the
- * internal buffers of this streams.
- *
- * @param in the input stream to read from
- * @return total number of bytes read from the input stream
- * (and written to this stream)
- * @throws IOException if an I/O error occurs while reading the input stream
- * @since Commons IO 1.4
- */
- public synchronized int write(InputStream in) throws IOException {
- int readCount = 0;
- int inBufferPos = count - filledBufferSum;
- int n = in.read(currentBuffer, inBufferPos, currentBuffer.length - inBufferPos);
- while (n != -1) {
- readCount += n;
- inBufferPos += n;
- count += n;
- if (inBufferPos == currentBuffer.length) {
- needNewBuffer(currentBuffer.length);
- inBufferPos = 0;
- }
- n = in.read(currentBuffer, inBufferPos, currentBuffer.length - inBufferPos);
- }
- return readCount;
- }
-
- /**
- * Return the current size of the byte array.
- * @return the current size of the byte array
- */
- public synchronized int size() {
- return count;
- }
-
- /**
- * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
- * this class can be called after the stream has been closed without
- * generating an <tt>IOException</tt>.
- *
- * @throws IOException never (this method should not declare this exception
- * but it has to now due to backwards compatability)
- */
- public void close() throws IOException {
- //nop
- }
-
- /**
- * @see java.io.ByteArrayOutputStream#reset()
- */
- public synchronized void reset() {
- count = 0;
- filledBufferSum = 0;
- currentBufferIndex = 0;
- currentBuffer = getBuffer(currentBufferIndex);
- }
-
- /**
- * Writes the entire contents of this byte stream to the
- * specified output stream.
- *
- * @param out the output stream to write to
- * @throws IOException if an I/O error occurs, such as if the stream is closed
- * @see java.io.ByteArrayOutputStream#writeTo(OutputStream)
- */
- public synchronized void writeTo(OutputStream out) throws IOException {
- int remaining = count;
- for (int i = 0; i < buffers.size(); i++) {
- byte[] buf = getBuffer(i);
- int c = Math.min(buf.length, remaining);
- out.write(buf, 0, c);
- remaining -= c;
- if (remaining == 0) {
- break;
- }
- }
- }
-
- /**
- * Gets the curent contents of this byte stream as a byte array.
- * The result is independent of this stream.
- *
- * @return the current contents of this output stream, as a byte array
- * @see java.io.ByteArrayOutputStream#toByteArray()
- */
- public synchronized byte[] toByteArray() {
- int remaining = count;
- if (remaining == 0) {
- return EMPTY_BYTE_ARRAY;
- }
- byte newbuf[] = new byte[remaining];
- int pos = 0;
- for (int i = 0; i < buffers.size(); i++) {
- byte[] buf = getBuffer(i);
- int c = Math.min(buf.length, remaining);
- System.arraycopy(buf, 0, newbuf, pos, c);
- pos += c;
- remaining -= c;
- if (remaining == 0) {
- break;
- }
- }
- return newbuf;
- }
-
- /**
- * Gets the curent contents of this byte stream as a string.
- * @return the contents of the byte array as a String
- * @see java.io.ByteArrayOutputStream#toString()
- */
- public String toString() {
- return new String(toByteArray());
- }
-
- /**
- * Gets the curent contents of this byte stream as a string
- * using the specified encoding.
- *
- * @param enc the name of the character encoding
- * @return the string converted from the byte array
- * @throws UnsupportedEncodingException if the encoding is not supported
- * @see java.io.ByteArrayOutputStream#toString(String)
- */
- public String toString(String enc) throws UnsupportedEncodingException {
- return new String(toByteArray(), enc);
- }
-
-}
diff --git a/src/org/apache/commons/io/output/CloseShieldOutputStream.java b/src/org/apache/commons/io/output/CloseShieldOutputStream.java
deleted file mode 100644
index 63f44be40..000000000
--- a/src/org/apache/commons/io/output/CloseShieldOutputStream.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.output;
-
-import java.io.OutputStream;
-
-/**
- * Proxy stream that prevents the underlying output stream from being closed.
- * <p>
- * This class is typically used in cases where an output stream needs to be
- * passed to a component that wants to explicitly close the stream even if
- * other components would still use the stream for output.
- *
- * @version $Id: CloseShieldOutputStream.java 587913 2007-10-24 15:47:30Z niallp $
- * @since Commons IO 1.4
- */
-public class CloseShieldOutputStream extends ProxyOutputStream {
-
- /**
- * Creates a proxy that shields the given output stream from being
- * closed.
- *
- * @param out underlying output stream
- */
- public CloseShieldOutputStream(OutputStream out) {
- super(out);
- }
-
- /**
- * Replaces the underlying output stream with a {@link ClosedOutputStream}
- * sentinel. The original output stream will remain open, but this proxy
- * will appear closed.
- */
- public void close() {
- out = new ClosedOutputStream();
- }
-
-}
diff --git a/src/org/apache/commons/io/output/ClosedOutputStream.java b/src/org/apache/commons/io/output/ClosedOutputStream.java
deleted file mode 100644
index b585c0cf4..000000000
--- a/src/org/apache/commons/io/output/ClosedOutputStream.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.output;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Closed output stream. This stream throws an exception on all attempts to
- * write something to the stream.
- * <p>
- * Typically uses of this class include testing for corner cases in methods
- * that accept an output stream and acting as a sentinel value instead of
- * a <code>null</code> output stream.
- *
- * @version $Id: ClosedOutputStream.java 601751 2007-12-06 14:55:45Z niallp $
- * @since Commons IO 1.4
- */
-public class ClosedOutputStream extends OutputStream {
-
- /**
- * A singleton.
- */
- public static final ClosedOutputStream CLOSED_OUTPUT_STREAM = new ClosedOutputStream();
-
- /**
- * Throws an {@link IOException} to indicate that the stream is closed.
- *
- * @param b ignored
- * @throws IOException always thrown
- */
- public void write(int b) throws IOException {
- throw new IOException("write(" + b + ") failed: stream is closed");
- }
-
-}
diff --git a/src/org/apache/commons/io/output/CountingOutputStream.java b/src/org/apache/commons/io/output/CountingOutputStream.java
deleted file mode 100644
index 672882860..000000000
--- a/src/org/apache/commons/io/output/CountingOutputStream.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.output;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * A decorating output stream that counts the number of bytes that have passed
- * through the stream so far.
- * <p>
- * A typical use case would be during debugging, to ensure that data is being
- * written as expected.
- *
- * @version $Id: CountingOutputStream.java 471628 2006-11-06 04:06:45Z bayard $
- */
-public class CountingOutputStream extends ProxyOutputStream {
-
- /** The count of bytes that have passed. */
- private long count;
-
- /**
- * Constructs a new CountingOutputStream.
- *
- * @param out the OutputStream to write to
- */
- public CountingOutputStream( OutputStream out ) {
- super(out);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Writes the contents of the specified byte array to this output stream
- * keeping count of the number of bytes written.
- *
- * @param b the bytes to write, not null
- * @throws IOException if an I/O error occurs
- * @see java.io.OutputStream#write(byte[])
- */
- public void write(byte[] b) throws IOException {
- count += b.length;
- super.write(b);
- }
-
- /**
- * Writes a portion of the specified byte array to this output stream
- * keeping count of the number of bytes written.
- *
- * @param b the bytes to write, not null
- * @param off the start offset in the buffer
- * @param len the maximum number of bytes to write
- * @throws IOException if an I/O error occurs
- * @see java.io.OutputStream#write(byte[], int, int)
- */
- public void write(byte[] b, int off, int len) throws IOException {
- count += len;
- super.write(b, off, len);
- }
-
- /**
- * Writes a single byte to the output stream adding to the count of the
- * number of bytes written.
- *
- * @param b the byte to write
- * @throws IOException if an I/O error occurs
- * @see java.io.OutputStream#write(int)
- */
- public void write(int b) throws IOException {
- count++;
- super.write(b);
- }
-
- //-----------------------------------------------------------------------
- /**
- * The number of bytes that have passed through this stream.
- * <p>
- * NOTE: From v1.3 this method throws an ArithmeticException if the
- * count is greater than can be expressed by an <code>int</code>.
- * See {@link #getByteCount()} for a method using a <code>long</code>.
- *
- * @return the number of bytes accumulated
- * @throws ArithmeticException if the byte count is too large
- */
- public synchronized int getCount() {
- long result = getByteCount();
- if (result > Integer.MAX_VALUE) {
- throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int");
- }
- return (int) result;
- }
-
- /**
- * Set the byte count back to 0.
- * <p>
- * NOTE: From v1.3 this method throws an ArithmeticException if the
- * count is greater than can be expressed by an <code>int</code>.
- * See {@link #resetByteCount()} for a method using a <code>long</code>.
- *
- * @return the count previous to resetting
- * @throws ArithmeticException if the byte count is too large
- */
- public synchronized int resetCount() {
- long result = resetByteCount();
- if (result > Integer.MAX_VALUE) {
- throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int");
- }
- return (int) result;
- }
-
- /**
- * The number of bytes that have passed through this stream.
- * <p>
- * NOTE: This method is an alternative for <code>getCount()</code>.
- * It was added because that method returns an integer which will
- * result in incorrect count for files over 2GB.
- *
- * @return the number of bytes accumulated
- * @since Commons IO 1.3
- */
- public synchronized long getByteCount() {
- return this.count;
- }
-
- /**
- * Set the byte count back to 0.
- * <p>
- * NOTE: This method is an alternative for <code>resetCount()</code>.
- * It was added because that method returns an integer which will
- * result in incorrect count for files over 2GB.
- *
- * @return the count previous to resetting
- * @since Commons IO 1.3
- */
- public synchronized long resetByteCount() {
- long tmp = this.count;
- this.count = 0;
- return tmp;
- }
-
-}
diff --git a/src/org/apache/commons/io/output/DeferredFileOutputStream.java b/src/org/apache/commons/io/output/DeferredFileOutputStream.java
deleted file mode 100644
index b8a9e9607..000000000
--- a/src/org/apache/commons/io/output/DeferredFileOutputStream.java
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.output;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.apache.commons.io.IOUtils;
-
-
-/**
- * An output stream which will retain data in memory until a specified
- * threshold is reached, and only then commit it to disk. If the stream is
- * closed before the threshold is reached, the data will not be written to
- * disk at all.
- * <p>
- * This class originated in FileUpload processing. In this use case, you do
- * not know in advance the size of the file being uploaded. If the file is small
- * you want to store it in memory (for speed), but if the file is large you want
- * to store it to file (to avoid memory issues).
- *
- * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
- * @author gaxzerow
- *
- * @version $Id: DeferredFileOutputStream.java 606381 2007-12-22 02:03:16Z ggregory $
- */
-public class DeferredFileOutputStream
- extends ThresholdingOutputStream
-{
-
- // ----------------------------------------------------------- Data members
-
-
- /**
- * The output stream to which data will be written prior to the theshold
- * being reached.
- */
- private ByteArrayOutputStream memoryOutputStream;
-
-
- /**
- * The output stream to which data will be written at any given time. This
- * will always be one of <code>memoryOutputStream</code> or
- * <code>diskOutputStream</code>.
- */
- private OutputStream currentOutputStream;
-
-
- /**
- * The file to which output will be directed if the threshold is exceeded.
- */
- private File outputFile;
-
- /**
- * The temporary file prefix.
- */
- private String prefix;
-
- /**
- * The temporary file suffix.
- */
- private String suffix;
-
- /**
- * The directory to use for temporary files.
- */
- private File directory;
-
-
- /**
- * True when close() has been called successfully.
- */
- private boolean closed = false;
-
- // ----------------------------------------------------------- Constructors
-
-
- /**
- * Constructs an instance of this class which will trigger an event at the
- * specified threshold, and save data to a file beyond that point.
- *
- * @param threshold The number of bytes at which to trigger an event.
- * @param outputFile The file to which data is saved beyond the threshold.
- */
- public DeferredFileOutputStream(int threshold, File outputFile)
- {
- super(threshold);
- this.outputFile = outputFile;
-
- memoryOutputStream = new ByteArrayOutputStream();
- currentOutputStream = memoryOutputStream;
- }
-
-
- /**
- * Constructs an instance of this class which will trigger an event at the
- * specified threshold, and save data to a temporary file beyond that point.
- *
- * @param threshold The number of bytes at which to trigger an event.
- * @param prefix Prefix to use for the temporary file.
- * @param suffix Suffix to use for the temporary file.
- * @param directory Temporary file directory.
- *
- * @since Commons IO 1.4
- */
- public DeferredFileOutputStream(int threshold, String prefix, String suffix, File directory)
- {
- this(threshold, (File)null);
- if (prefix == null) {
- throw new IllegalArgumentException("Temporary file prefix is missing");
- }
- this.prefix = prefix;
- this.suffix = suffix;
- this.directory = directory;
- }
-
-
- // --------------------------------------- ThresholdingOutputStream methods
-
-
- /**
- * Returns the current output stream. This may be memory based or disk
- * based, depending on the current state with respect to the threshold.
- *
- * @return The underlying output stream.
- *
- * @exception IOException if an error occurs.
- */
- protected OutputStream getStream() throws IOException
- {
- return currentOutputStream;
- }
-
-
- /**
- * Switches the underlying output stream from a memory based stream to one
- * that is backed by disk. This is the point at which we realise that too
- * much data is being written to keep in memory, so we elect to switch to
- * disk-based storage.
- *
- * @exception IOException if an error occurs.
- */
- protected void thresholdReached() throws IOException
- {
- if (prefix != null) {
- outputFile = File.createTempFile(prefix, suffix, directory);
- }
- FileOutputStream fos = new FileOutputStream(outputFile);
- memoryOutputStream.writeTo(fos);
- currentOutputStream = fos;
- memoryOutputStream = null;
- }
-
-
- // --------------------------------------------------------- Public methods
-
-
- /**
- * Determines whether or not the data for this output stream has been
- * retained in memory.
- *
- * @return <code>true</code> if the data is available in memory;
- * <code>false</code> otherwise.
- */
- public boolean isInMemory()
- {
- return (!isThresholdExceeded());
- }
-
-
- /**
- * Returns the data for this output stream as an array of bytes, assuming
- * that the data has been retained in memory. If the data was written to
- * disk, this method returns <code>null</code>.
- *
- * @return The data for this output stream, or <code>null</code> if no such
- * data is available.
- */
- public byte[] getData()
- {
- if (memoryOutputStream != null)
- {
- return memoryOutputStream.toByteArray();
- }
- return null;
- }
-
-
- /**
- * Returns either the output file specified in the constructor or
- * the temporary file created or null.
- * <p>
- * If the constructor specifying the file is used then it returns that
- * same output file, even when threashold has not been reached.
- * <p>
- * If constructor specifying a temporary file prefix/suffix is used
- * then the temporary file created once the threashold is reached is returned
- * If the threshold was not reached then <code>null</code> is returned.
- *
- * @return The file for this output stream, or <code>null</code> if no such
- * file exists.
- */
- public File getFile()
- {
- return outputFile;
- }
-
-
- /**
- * Closes underlying output stream, and mark this as closed
- *
- * @exception IOException if an error occurs.
- */
- public void close() throws IOException
- {
- super.close();
- closed = true;
- }
-
-
- /**
- * Writes the data from this output stream to the specified output stream,
- * after it has been closed.
- *
- * @param out output stream to write to.
- * @exception IOException if this stream is not yet closed or an error occurs.
- */
- public void writeTo(OutputStream out) throws IOException
- {
- // we may only need to check if this is closed if we are working with a file
- // but we should force the habit of closing wether we are working with
- // a file or memory.
- if (!closed)
- {
- throw new IOException("Stream not closed");
- }
-
- if(isInMemory())
- {
- memoryOutputStream.writeTo(out);
- }
- else
- {
- FileInputStream fis = new FileInputStream(outputFile);
- try {
- IOUtils.copy(fis, out);
- } finally {
- IOUtils.closeQuietly(fis);
- }
- }
- }
-}
diff --git a/src/org/apache/commons/io/output/DemuxOutputStream.java b/src/org/apache/commons/io/output/DemuxOutputStream.java
deleted file mode 100644
index 086911118..000000000
--- a/src/org/apache/commons/io/output/DemuxOutputStream.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.output;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Data written to this stream is forwarded to a stream that has been associated
- * with this thread.
- *
- * @author <a href="mailto:peter@apache.org">Peter Donald</a>
- * @version $Revision: 437567 $ $Date: 2006-08-28 07:39:07 +0100 (Mon, 28 Aug 2006) $
- */
-public class DemuxOutputStream
- extends OutputStream
-{
- private InheritableThreadLocal m_streams = new InheritableThreadLocal();
-
- /**
- * Bind the specified stream to the current thread.
- *
- * @param output the stream to bind
- * @return the OutputStream that was previously active
- */
- public OutputStream bindStream( OutputStream output )
- {
- OutputStream stream = getStream();
- m_streams.set( output );
- return stream;
- }
-
- /**
- * Closes stream associated with current thread.
- *
- * @throws IOException if an error occurs
- */
- public void close()
- throws IOException
- {
- OutputStream output = getStream();
- if( null != output )
- {
- output.close();
- }
- }
-
- /**
- * Flushes stream associated with current thread.
- *
- * @throws IOException if an error occurs
- */
- public void flush()
- throws IOException
- {
- OutputStream output = getStream();
- if( null != output )
- {
- output.flush();
- }
- }
-
- /**
- * Writes byte to stream associated with current thread.
- *
- * @param ch the byte to write to stream
- * @throws IOException if an error occurs
- */
- public void write( int ch )
- throws IOException
- {
- OutputStream output = getStream();
- if( null != output )
- {
- output.write( ch );
- }
- }
-
- /**
- * Utility method to retrieve stream bound to current thread (if any).
- *
- * @return the output stream
- */
- private OutputStream getStream()
- {
- return (OutputStream)m_streams.get();
- }
-}
diff --git a/src/org/apache/commons/io/output/FileWriterWithEncoding.java b/src/org/apache/commons/io/output/FileWriterWithEncoding.java
deleted file mode 100644
index a8f89334b..000000000
--- a/src/org/apache/commons/io/output/FileWriterWithEncoding.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.output;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-
-/**
- * Writer of files that allows the encoding to be set.
- * <p>
- * This class provides a simple alternative to <code>FileWriter</code>
- * that allows an encoding to be set. Unfortunately, it cannot subclass
- * <code>FileWriter</code>.
- * <p>
- * By default, the file will be overwritten, but this may be changed to append.
- * <p>
- * The encoding must be specified using either the name of the {@link Charset},
- * the {@link Charset}, or a {@link CharsetEncoder}. If the default encoding
- * is required then use the {@link java.io.FileWriter} directly, rather than
- * this implementation.
- * <p>
- *
- *
- * @since Commons IO 1.4
- * @version $Id: FileWriterWithEncoding.java 611634 2008-01-13 20:35:00Z niallp $
- */
-public class FileWriterWithEncoding extends Writer {
- // Cannot extend ProxyWriter, as requires writer to be
- // known when super() is called
-
- /** The writer to decorate. */
- private final Writer out;
-
- /**
- * Constructs a FileWriterWithEncoding with a file encoding.
- *
- * @param filename the name of the file to write to, not null
- * @param encoding the encoding to use, not null
- * @throws NullPointerException if the file name or encoding is null
- * @throws IOException in case of an I/O error
- */
- public FileWriterWithEncoding(String filename, String encoding) throws IOException {
- this(new File(filename), encoding, false);
- }
-
- /**
- * Constructs a FileWriterWithEncoding with a file encoding.
- *
- * @param filename the name of the file to write to, not null
- * @param encoding the encoding to use, not null
- * @param append true if content should be appended, false to overwrite
- * @throws NullPointerException if the file name or encoding is null
- * @throws IOException in case of an I/O error
- */
- public FileWriterWithEncoding(String filename, String encoding, boolean append) throws IOException {
- this(new File(filename), encoding, append);
- }
-
- /**
- * Constructs a FileWriterWithEncoding with a file encoding.
- *
- * @param filename the name of the file to write to, not null
- * @param encoding the encoding to use, not null
- * @throws NullPointerException if the file name or encoding is null
- * @throws IOException in case of an I/O error
- */
- public FileWriterWithEncoding(String filename, Charset encoding) throws IOException {
- this(new File(filename), encoding, false);
- }
-
- /**
- * Constructs a FileWriterWithEncoding with a file encoding.
- *
- * @param filename the name of the file to write to, not null
- * @param encoding the encoding to use, not null
- * @param append true if content should be appended, false to overwrite
- * @throws NullPointerException if the file name or encoding is null
- * @throws IOException in case of an I/O error
- */
- public FileWriterWithEncoding(String filename, Charset encoding, boolean append) throws IOException {
- this(new File(filename), encoding, append);
- }
-
- /**
- * Constructs a FileWriterWithEncoding with a file encoding.
- *
- * @param filename the name of the file to write to, not null
- * @param encoding the encoding to use, not null
- * @throws NullPointerException if the file name or encoding is null
- * @throws IOException in case of an I/O error
- */
- public FileWriterWithEncoding(String filename, CharsetEncoder encoding) throws IOException {
- this(new File(filename), encoding, false);
- }
-
- /**
- * Constructs a FileWriterWithEncoding with a file encoding.
- *
- * @param filename the name of the file to write to, not null
- * @param encoding the encoding to use, not null
- * @param append true if content should be appended, false to overwrite
- * @throws NullPointerException if the file name or encoding is null
- * @throws IOException in case of an I/O error
- */
- public FileWriterWithEncoding(String filename, CharsetEncoder encoding, boolean append) throws IOException {
- this(new File(filename), encoding, append);
- }
-
- /**
- * Constructs a FileWriterWithEncoding with a file encoding.
- *
- * @param file the file to write to, not null
- * @param encoding the encoding to use, not null
- * @throws NullPointerException if the file or encoding is null
- * @throws IOException in case of an I/O error
- */
- public FileWriterWithEncoding(File file, String encoding) throws IOException {
- this(file, encoding, false);
- }
-
- /**
- * Constructs a FileWriterWithEncoding with a file encoding.
- *
- * @param file the file to write to, not null
- * @param encoding the encoding to use, not null
- * @param append true if content should be appended, false to overwrite
- * @throws NullPointerException if the file or encoding is null
- * @throws IOException in case of an I/O error
- */
- public FileWriterWithEncoding(File file, String encoding, boolean append) throws IOException {
- super();
- this.out = initWriter(file, encoding, append);
- }
-
- /**
- * Constructs a FileWriterWithEncoding with a file encoding.
- *
- * @param file the file to write to, not null
- * @param encoding the encoding to use, not null
- * @throws NullPointerException if the file or encoding is null
- * @throws IOException in case of an I/O error
- */
- public FileWriterWithEncoding(File file, Charset encoding) throws IOException {
- this(file, encoding, false);
- }
-
- /**
- * Constructs a FileWriterWithEncoding with a file encoding.
- *
- * @param file the file to write to, not null
- * @param encoding the encoding to use, not null
- * @param append true if content should be appended, false to overwrite
- * @throws NullPointerException if the file or encoding is null
- * @throws IOException in case of an I/O error
- */
- public FileWriterWithEncoding(File file, Charset encoding, boolean append) throws IOException {
- super();
- this.out = initWriter(file, encoding, append);
- }
-
- /**
- * Constructs a FileWriterWithEncoding with a file encoding.
- *
- * @param file the file to write to, not null
- * @param encoding the encoding to use, not null
- * @throws NullPointerException if the file or encoding is null
- * @throws IOException in case of an I/O error
- */
- public FileWriterWithEncoding(File file, CharsetEncoder encoding) throws IOException {
- this(file, encoding, false);
- }
-
- /**
- * Constructs a FileWriterWithEncoding with a file encoding.
- *
- * @param file the file to write to, not null
- * @param encoding the encoding to use, not null
- * @param append true if content should be appended, false to overwrite
- * @throws NullPointerException if the file or encoding is null
- * @throws IOException in case of an I/O error
- */
- public FileWriterWithEncoding(File file, CharsetEncoder encoding, boolean append) throws IOException {
- super();
- this.out = initWriter(file, encoding, append);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Initialise the wrapped file writer.
- * Ensure that a cleanup occurs if the writer creation fails.
- *
- * @param file the file to be accessed
- * @param encoding the encoding to use - may be Charset, CharsetEncoder or String
- * @param append true to append
- * @return the initialised writer
- * @throws NullPointerException if the file or encoding is null
- * @throws IOException if an error occurs
- */
- private static Writer initWriter(File file, Object encoding, boolean append) throws IOException {
- if (file == null) {
- throw new NullPointerException("File is missing");
- }
- if (encoding == null) {
- throw new NullPointerException("Encoding is missing");
- }
- boolean fileExistedAlready = file.exists();
- OutputStream stream = null;
- Writer writer = null;
- try {
- stream = new FileOutputStream(file, append);
- if (encoding instanceof Charset) {
- writer = new OutputStreamWriter(stream, (Charset)encoding);
- } else if (encoding instanceof CharsetEncoder) {
- writer = new OutputStreamWriter(stream, (CharsetEncoder)encoding);
- } else {
- writer = new OutputStreamWriter(stream, (String)encoding);
- }
- } catch (IOException ex) {
- IOUtils.closeQuietly(writer);
- IOUtils.closeQuietly(stream);
- if (fileExistedAlready == false) {
- FileUtils.deleteQuietly(file);
- }
- throw ex;
- } catch (RuntimeException ex) {
- IOUtils.closeQuietly(writer);
- IOUtils.closeQuietly(stream);
- if (fileExistedAlready == false) {
- FileUtils.deleteQuietly(file);
- }
- throw ex;
- }
- return writer;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Write a character.
- * @param idx the character to write
- * @throws IOException if an I/O error occurs
- */
- public void write(int idx) throws IOException {
- out.write(idx);
- }
-
- /**
- * Write the characters from an array.
- * @param chr the characters to write
- * @throws IOException if an I/O error occurs
- */
- public void write(char[] chr) throws IOException {
- out.write(chr);
- }
-
- /**
- * Write the specified characters from an array.
- * @param chr the characters to write
- * @param st The start offset
- * @param end The number of characters to write
- * @throws IOException if an I/O error occurs
- */
- public void write(char[] chr, int st, int end) throws IOException {
- out.write(chr, st, end);
- }
-
- /**
- * Write the characters from a string.
- * @param str the string to write
- * @throws IOException if an I/O error occurs
- */
- public void write(String str) throws IOException {
- out.write(str);
- }
-
- /**
- * Write the specified characters from a string.
- * @param str the string to write
- * @param st The start offset
- * @param end The number of characters to write
- * @throws IOException if an I/O error occurs
- */
- public void write(String str, int st, int end) throws IOException {
- out.write(str, st, end);
- }
-
- /**
- * Flush the stream.
- * @throws IOException if an I/O error occurs
- */
- public void flush() throws IOException {
- out.flush();
- }
-
- /**
- * Close the stream.
- * @throws IOException if an I/O error occurs
- */
- public void close() throws IOException {
- out.close();
- }
-}
diff --git a/src/org/apache/commons/io/output/LockableFileWriter.java b/src/org/apache/commons/io/output/LockableFileWriter.java
deleted file mode 100644
index 6b10bd282..000000000
--- a/src/org/apache/commons/io/output/LockableFileWriter.java
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.output;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-
-/**
- * FileWriter that will create and honor lock files to allow simple
- * cross thread file lock handling.
- * <p>
- * This class provides a simple alternative to <code>FileWriter</code>
- * that will use a lock file to prevent duplicate writes.
- * <p>
- * By default, the file will be overwritten, but this may be changed to append.
- * The lock directory may be specified, but defaults to the system property
- * <code>java.io.tmpdir</code>.
- * The encoding may also be specified, and defaults to the platform default.
- *
- * @author <a href="mailto:sanders@apache.org">Scott Sanders</a>
- * @author <a href="mailto:ms@collab.net">Michael Salmon</a>
- * @author <a href="mailto:jon@collab.net">Jon S. Stevens</a>
- * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
- * @author Stephen Colebourne
- * @author Andy Lehane
- * @version $Id: LockableFileWriter.java 610010 2008-01-08 14:50:59Z niallp $
- */
-public class LockableFileWriter extends Writer {
- // Cannot extend ProxyWriter, as requires writer to be
- // known when super() is called
-
- /** The extension for the lock file. */
- private static final String LCK = ".lck";
-
- /** The writer to decorate. */
- private final Writer out;
- /** The lock file. */
- private final File lockFile;
-
- /**
- * Constructs a LockableFileWriter.
- * If the file exists, it is overwritten.
- *
- * @param fileName the file to write to, not null
- * @throws NullPointerException if the file is null
- * @throws IOException in case of an I/O error
- */
- public LockableFileWriter(String fileName) throws IOException {
- this(fileName, false, null);
- }
-
- /**
- * Constructs a LockableFileWriter.
- *
- * @param fileName file to write to, not null
- * @param append true if content should be appended, false to overwrite
- * @throws NullPointerException if the file is null
- * @throws IOException in case of an I/O error
- */
- public LockableFileWriter(String fileName, boolean append) throws IOException {
- this(fileName, append, null);
- }
-
- /**
- * Constructs a LockableFileWriter.
- *
- * @param fileName the file to write to, not null
- * @param append true if content should be appended, false to overwrite
- * @param lockDir the directory in which the lock file should be held
- * @throws NullPointerException if the file is null
- * @throws IOException in case of an I/O error
- */
- public LockableFileWriter(String fileName, boolean append, String lockDir) throws IOException {
- this(new File(fileName), append, lockDir);
- }
-
- /**
- * Constructs a LockableFileWriter.
- * If the file exists, it is overwritten.
- *
- * @param file the file to write to, not null
- * @throws NullPointerException if the file is null
- * @throws IOException in case of an I/O error
- */
- public LockableFileWriter(File file) throws IOException {
- this(file, false, null);
- }
-
- /**
- * Constructs a LockableFileWriter.
- *
- * @param file the file to write to, not null
- * @param append true if content should be appended, false to overwrite
- * @throws NullPointerException if the file is null
- * @throws IOException in case of an I/O error
- */
- public LockableFileWriter(File file, boolean append) throws IOException {
- this(file, append, null);
- }
-
- /**
- * Constructs a LockableFileWriter.
- *
- * @param file the file to write to, not null
- * @param append true if content should be appended, false to overwrite
- * @param lockDir the directory in which the lock file should be held
- * @throws NullPointerException if the file is null
- * @throws IOException in case of an I/O error
- */
- public LockableFileWriter(File file, boolean append, String lockDir) throws IOException {
- this(file, null, append, lockDir);
- }
-
- /**
- * Constructs a LockableFileWriter with a file encoding.
- *
- * @param file the file to write to, not null
- * @param encoding the encoding to use, null means platform default
- * @throws NullPointerException if the file is null
- * @throws IOException in case of an I/O error
- */
- public LockableFileWriter(File file, String encoding) throws IOException {
- this(file, encoding, false, null);
- }
-
- /**
- * Constructs a LockableFileWriter with a file encoding.
- *
- * @param file the file to write to, not null
- * @param encoding the encoding to use, null means platform default
- * @param append true if content should be appended, false to overwrite
- * @param lockDir the directory in which the lock file should be held
- * @throws NullPointerException if the file is null
- * @throws IOException in case of an I/O error
- */
- public LockableFileWriter(File file, String encoding, boolean append,
- String lockDir) throws IOException {
- super();
- // init file to create/append
- file = file.getAbsoluteFile();
- if (file.getParentFile() != null) {
- FileUtils.forceMkdir(file.getParentFile());
- }
- if (file.isDirectory()) {
- throw new IOException("File specified is a directory");
- }
-
- // init lock file
- if (lockDir == null) {
- lockDir = System.getProperty("java.io.tmpdir");
- }
- File lockDirFile = new File(lockDir);
- FileUtils.forceMkdir(lockDirFile);
- testLockDir(lockDirFile);
- lockFile = new File(lockDirFile, file.getName() + LCK);
-
- // check if locked
- createLock();
-
- // init wrapped writer
- out = initWriter(file, encoding, append);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Tests that we can write to the lock directory.
- *
- * @param lockDir the File representing the lock directory
- * @throws IOException if we cannot write to the lock directory
- * @throws IOException if we cannot find the lock file
- */
- private void testLockDir(File lockDir) throws IOException {
- if (!lockDir.exists()) {
- throw new IOException(
- "Could not find lockDir: " + lockDir.getAbsolutePath());
- }
- if (!lockDir.canWrite()) {
- throw new IOException(
- "Could not write to lockDir: " + lockDir.getAbsolutePath());
- }
- }
-
- /**
- * Creates the lock file.
- *
- * @throws IOException if we cannot create the file
- */
- private void createLock() throws IOException {
- synchronized (LockableFileWriter.class) {
- if (!lockFile.createNewFile()) {
- throw new IOException("Can't write file, lock " +
- lockFile.getAbsolutePath() + " exists");
- }
- lockFile.deleteOnExit();
- }
- }
-
- /**
- * Initialise the wrapped file writer.
- * Ensure that a cleanup occurs if the writer creation fails.
- *
- * @param file the file to be accessed
- * @param encoding the encoding to use
- * @param append true to append
- * @return The initialised writer
- * @throws IOException if an error occurs
- */
- private Writer initWriter(File file, String encoding, boolean append) throws IOException {
- boolean fileExistedAlready = file.exists();
- OutputStream stream = null;
- Writer writer = null;
- try {
- if (encoding == null) {
- writer = new FileWriter(file.getAbsolutePath(), append);
- } else {
- stream = new FileOutputStream(file.getAbsolutePath(), append);
- writer = new OutputStreamWriter(stream, encoding);
- }
- } catch (IOException ex) {
- IOUtils.closeQuietly(writer);
- IOUtils.closeQuietly(stream);
- lockFile.delete();
- if (fileExistedAlready == false) {
- file.delete();
- }
- throw ex;
- } catch (RuntimeException ex) {
- IOUtils.closeQuietly(writer);
- IOUtils.closeQuietly(stream);
- lockFile.delete();
- if (fileExistedAlready == false) {
- file.delete();
- }
- throw ex;
- }
- return writer;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Closes the file writer.
- *
- * @throws IOException if an I/O error occurs
- */
- public void close() throws IOException {
- try {
- out.close();
- } finally {
- lockFile.delete();
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Write a character.
- * @param idx the character to write
- * @throws IOException if an I/O error occurs
- */
- public void write(int idx) throws IOException {
- out.write(idx);
- }
-
- /**
- * Write the characters from an array.
- * @param chr the characters to write
- * @throws IOException if an I/O error occurs
- */
- public void write(char[] chr) throws IOException {
- out.write(chr);
- }
-
- /**
- * Write the specified characters from an array.
- * @param chr the characters to write
- * @param st The start offset
- * @param end The number of characters to write
- * @throws IOException if an I/O error occurs
- */
- public void write(char[] chr, int st, int end) throws IOException {
- out.write(chr, st, end);
- }
-
- /**
- * Write the characters from a string.
- * @param str the string to write
- * @throws IOException if an I/O error occurs
- */
- public void write(String str) throws IOException {
- out.write(str);
- }
-
- /**
- * Write the specified characters from a string.
- * @param str the string to write
- * @param st The start offset
- * @param end The number of characters to write
- * @throws IOException if an I/O error occurs
- */
- public void write(String str, int st, int end) throws IOException {
- out.write(str, st, end);
- }
-
- /**
- * Flush the stream.
- * @throws IOException if an I/O error occurs
- */
- public void flush() throws IOException {
- out.flush();
- }
-
-}
diff --git a/src/org/apache/commons/io/output/NullOutputStream.java b/src/org/apache/commons/io/output/NullOutputStream.java
deleted file mode 100644
index 7e3cdaf2c..000000000
--- a/src/org/apache/commons/io/output/NullOutputStream.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.output;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * This OutputStream writes all data to the famous <b>/dev/null</b>.
- * <p>
- * This output stream has no destination (file/socket etc.) and all
- * bytes written to it are ignored and lost.
- *
- * @author Jeremias Maerki
- * @version $Id: NullOutputStream.java 610010 2008-01-08 14:50:59Z niallp $
- */
-public class NullOutputStream extends OutputStream {
-
- /**
- * A singleton.
- */
- public static final NullOutputStream NULL_OUTPUT_STREAM = new NullOutputStream();
-
- /**
- * Does nothing - output to <code>/dev/null</code>.
- * @param b The bytes to write
- * @param off The start offset
- * @param len The number of bytes to write
- */
- public void write(byte[] b, int off, int len) {
- //to /dev/null
- }
-
- /**
- * Does nothing - output to <code>/dev/null</code>.
- * @param b The byte to write
- */
- public void write(int b) {
- //to /dev/null
- }
-
- /**
- * Does nothing - output to <code>/dev/null</code>.
- * @param b The bytes to write
- * @throws IOException never
- */
- public void write(byte[] b) throws IOException {
- //to /dev/null
- }
-
-}
diff --git a/src/org/apache/commons/io/output/NullWriter.java b/src/org/apache/commons/io/output/NullWriter.java
deleted file mode 100644
index aed52aba8..000000000
--- a/src/org/apache/commons/io/output/NullWriter.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.output;
-
-import java.io.Writer;
-
-/**
- * This {@link Writer} writes all data to the famous <b>/dev/null</b>.
- * <p>
- * This <code>Writer</code> has no destination (file/socket etc.) and all
- * characters written to it are ignored and lost.
- *
- * @version $Id: NullWriter.java 610010 2008-01-08 14:50:59Z niallp $
- */
-public class NullWriter extends Writer {
-
- /**
- * A singleton.
- */
- public static final NullWriter NULL_WRITER = new NullWriter();
-
- /**
- * Constructs a new NullWriter.
- */
- public NullWriter() {
- }
-
- /**
- * Does nothing - output to <code>/dev/null</code>.
- * @param idx The character to write
- */
- public void write(int idx) {
- //to /dev/null
- }
-
- /**
- * Does nothing - output to <code>/dev/null</code>.
- * @param chr The characters to write
- */
- public void write(char[] chr) {
- //to /dev/null
- }
-
- /**
- * Does nothing - output to <code>/dev/null</code>.
- * @param chr The characters to write
- * @param st The start offset
- * @param end The number of characters to write
- */
- public void write(char[] chr, int st, int end) {
- //to /dev/null
- }
-
- /**
- * Does nothing - output to <code>/dev/null</code>.
- * @param str The string to write
- */
- public void write(String str) {
- //to /dev/null
- }
-
- /**
- * Does nothing - output to <code>/dev/null</code>.
- * @param str The string to write
- * @param st The start offset
- * @param end The number of characters to write
- */
- public void write(String str, int st, int end) {
- //to /dev/null
- }
-
- /** @see java.io.Writer#flush() */
- public void flush() {
- //to /dev/null
- }
-
- /** @see java.io.Writer#close() */
- public void close() {
- //to /dev/null
- }
-
-}
diff --git a/src/org/apache/commons/io/output/ProxyOutputStream.java b/src/org/apache/commons/io/output/ProxyOutputStream.java
deleted file mode 100644
index b63d72317..000000000
--- a/src/org/apache/commons/io/output/ProxyOutputStream.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.output;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * A Proxy stream which acts as expected, that is it passes the method
- * calls on to the proxied stream and doesn't change which methods are
- * being called. It is an alternative base class to FilterOutputStream
- * to increase reusability.
- *
- * @author Stephen Colebourne
- * @version $Id: ProxyOutputStream.java 610010 2008-01-08 14:50:59Z niallp $
- */
-public class ProxyOutputStream extends FilterOutputStream {
-
- /**
- * Constructs a new ProxyOutputStream.
- *
- * @param proxy the OutputStream to delegate to
- */
- public ProxyOutputStream(OutputStream proxy) {
- super(proxy);
- // the proxy is stored in a protected superclass variable named 'out'
- }
-
- /**
- * Invokes the delegate's <code>write(int)</code> method.
- * @param idx the byte to write
- * @throws IOException if an I/O error occurs
- */
- public void write(int idx) throws IOException {
- out.write(idx);
- }
-
- /**
- * Invokes the delegate's <code>write(byte[])</code> method.
- * @param bts the bytes to write
- * @throws IOException if an I/O error occurs
- */
- public void write(byte[] bts) throws IOException {
- out.write(bts);
- }
-
- /**
- * Invokes the delegate's <code>write(byte[])</code> method.
- * @param bts the bytes to write
- * @param st The start offset
- * @param end The number of bytes to write
- * @throws IOException if an I/O error occurs
- */
- public void write(byte[] bts, int st, int end) throws IOException {
- out.write(bts, st, end);
- }
-
- /**
- * Invokes the delegate's <code>flush()</code> method.
- * @throws IOException if an I/O error occurs
- */
- public void flush() throws IOException {
- out.flush();
- }
-
- /**
- * Invokes the delegate's <code>close()</code> method.
- * @throws IOException if an I/O error occurs
- */
- public void close() throws IOException {
- out.close();
- }
-
-}
diff --git a/src/org/apache/commons/io/output/ProxyWriter.java b/src/org/apache/commons/io/output/ProxyWriter.java
deleted file mode 100644
index fbec62885..000000000
--- a/src/org/apache/commons/io/output/ProxyWriter.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.output;
-
-import java.io.FilterWriter;
-import java.io.IOException;
-import java.io.Writer;
-
-/**
- * A Proxy stream which acts as expected, that is it passes the method
- * calls on to the proxied stream and doesn't change which methods are
- * being called. It is an alternative base class to FilterWriter
- * to increase reusability, because FilterWriter changes the
- * methods being called, such as write(char[]) to write(char[], int, int)
- * and write(String) to write(String, int, int).
- *
- * @author Stephen Colebourne
- * @version $Id: ProxyWriter.java 610010 2008-01-08 14:50:59Z niallp $
- */
-public class ProxyWriter extends FilterWriter {
-
- /**
- * Constructs a new ProxyWriter.
- *
- * @param proxy the Writer to delegate to
- */
- public ProxyWriter(Writer proxy) {
- super(proxy);
- // the proxy is stored in a protected superclass variable named 'out'
- }
-
- /**
- * Invokes the delegate's <code>write(int)</code> method.
- * @param idx the character to write
- * @throws IOException if an I/O error occurs
- */
- public void write(int idx) throws IOException {
- out.write(idx);
- }
-
- /**
- * Invokes the delegate's <code>write(char[])</code> method.
- * @param chr the characters to write
- * @throws IOException if an I/O error occurs
- */
- public void write(char[] chr) throws IOException {
- out.write(chr);
- }
-
- /**
- * Invokes the delegate's <code>write(char[], int, int)</code> method.
- * @param chr the characters to write
- * @param st The start offset
- * @param end The number of characters to write
- * @throws IOException if an I/O error occurs
- */
- public void write(char[] chr, int st, int end) throws IOException {
- out.write(chr, st, end);
- }
-
- /**
- * Invokes the delegate's <code>write(String)</code> method.
- * @param str the string to write
- * @throws IOException if an I/O error occurs
- */
- public void write(String str) throws IOException {
- out.write(str);
- }
-
- /**
- * Invokes the delegate's <code>write(String)</code> method.
- * @param str the string to write
- * @param st The start offset
- * @param end The number of characters to write
- * @throws IOException if an I/O error occurs
- */
- public void write(String str, int st, int end) throws IOException {
- out.write(str, st, end);
- }
-
- /**
- * Invokes the delegate's <code>flush()</code> method.
- * @throws IOException if an I/O error occurs
- */
- public void flush() throws IOException {
- out.flush();
- }
-
- /**
- * Invokes the delegate's <code>close()</code> method.
- * @throws IOException if an I/O error occurs
- */
- public void close() throws IOException {
- out.close();
- }
-
-}
diff --git a/src/org/apache/commons/io/output/TeeOutputStream.java b/src/org/apache/commons/io/output/TeeOutputStream.java
deleted file mode 100644
index ee957fb3b..000000000
--- a/src/org/apache/commons/io/output/TeeOutputStream.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.output;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Classic splitter of OutputStream. Named after the unix 'tee'
- * command. It allows a stream to be branched off so there
- * are now two streams.
- *
- * @version $Id: TeeOutputStream.java 610010 2008-01-08 14:50:59Z niallp $
- */
-public class TeeOutputStream extends ProxyOutputStream {
-
- /** the second OutputStream to write to */
- protected OutputStream branch;
-
- /**
- * Constructs a TeeOutputStream.
- * @param out the main OutputStream
- * @param branch the second OutputStream
- */
- public TeeOutputStream( OutputStream out, OutputStream branch ) {
- super(out);
- this.branch = branch;
- }
-
- /**
- * Write the bytes to both streams.
- * @param b the bytes to write
- * @throws IOException if an I/O error occurs
- */
- public synchronized void write(byte[] b) throws IOException {
- super.write(b);
- this.branch.write(b);
- }
-
- /**
- * Write the specified bytes to both streams.
- * @param b the bytes to write
- * @param off The start offset
- * @param len The number of bytes to write
- * @throws IOException if an I/O error occurs
- */
- public synchronized void write(byte[] b, int off, int len) throws IOException {
- super.write(b, off, len);
- this.branch.write(b, off, len);
- }
-
- /**
- * Write a byte to both streams.
- * @param b the byte to write
- * @throws IOException if an I/O error occurs
- */
- public synchronized void write(int b) throws IOException {
- super.write(b);
- this.branch.write(b);
- }
-
- /**
- * Flushes both streams.
- * @throws IOException if an I/O error occurs
- */
- public void flush() throws IOException {
- super.flush();
- this.branch.flush();
- }
-
- /**
- * Closes both streams.
- * @throws IOException if an I/O error occurs
- */
- public void close() throws IOException {
- super.close();
- this.branch.close();
- }
-
-}
diff --git a/src/org/apache/commons/io/output/ThresholdingOutputStream.java b/src/org/apache/commons/io/output/ThresholdingOutputStream.java
deleted file mode 100644
index fa69a804c..000000000
--- a/src/org/apache/commons/io/output/ThresholdingOutputStream.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.io.output;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-
-/**
- * An output stream which triggers an event when a specified number of bytes of
- * data have been written to it. The event can be used, for example, to throw
- * an exception if a maximum has been reached, or to switch the underlying
- * stream type when the threshold is exceeded.
- * <p>
- * This class overrides all <code>OutputStream</code> methods. However, these
- * overrides ultimately call the corresponding methods in the underlying output
- * stream implementation.
- * <p>
- * NOTE: This implementation may trigger the event <em>before</em> the threshold
- * is actually reached, since it triggers when a pending write operation would
- * cause the threshold to be exceeded.
- *
- * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
- *
- * @version $Id: ThresholdingOutputStream.java 540714 2007-05-22 19:39:44Z niallp $
- */
-public abstract class ThresholdingOutputStream
- extends OutputStream
-{
-
- // ----------------------------------------------------------- Data members
-
-
- /**
- * The threshold at which the event will be triggered.
- */
- private int threshold;
-
-
- /**
- * The number of bytes written to the output stream.
- */
- private long written;
-
-
- /**
- * Whether or not the configured threshold has been exceeded.
- */
- private boolean thresholdExceeded;
-
-
- // ----------------------------------------------------------- Constructors
-
-
- /**
- * Constructs an instance of this class which will trigger an event at the
- * specified threshold.
- *
- * @param threshold The number of bytes at which to trigger an event.
- */
- public ThresholdingOutputStream(int threshold)
- {
- this.threshold = threshold;
- }
-
-
- // --------------------------------------------------- OutputStream methods
-
-
- /**
- * Writes the specified byte to this output stream.
- *
- * @param b The byte to be written.
- *
- * @exception IOException if an error occurs.
- */
- public void write(int b) throws IOException
- {
- checkThreshold(1);
- getStream().write(b);
- written++;
- }
-
-
- /**
- * Writes <code>b.length</code> bytes from the specified byte array to this
- * output stream.
- *
- * @param b The array of bytes to be written.
- *
- * @exception IOException if an error occurs.
- */
- public void write(byte b[]) throws IOException
- {
- checkThreshold(b.length);
- getStream().write(b);
- written += b.length;
- }
-
-
- /**
- * Writes <code>len</code> bytes from the specified byte array starting at
- * offset <code>off</code> to this output stream.
- *
- * @param b The byte array from which the data will be written.
- * @param off The start offset in the byte array.
- * @param len The number of bytes to write.
- *
- * @exception IOException if an error occurs.
- */
- public void write(byte b[], int off, int len) throws IOException
- {
- checkThreshold(len);
- getStream().write(b, off, len);
- written += len;
- }
-
-
- /**
- * Flushes this output stream and forces any buffered output bytes to be
- * written out.
- *
- * @exception IOException if an error occurs.
- */
- public void flush() throws IOException
- {
- getStream().flush();
- }
-
-
- /**
- * Closes this output stream and releases any system resources associated
- * with this stream.
- *
- * @exception IOException if an error occurs.
- */
- public void close() throws IOException
- {
- try
- {
- flush();
- }
- catch (IOException ignored)
- {
- // ignore
- }
- getStream().close();
- }
-
-
- // --------------------------------------------------------- Public methods
-
-
- /**
- * Returns the threshold, in bytes, at which an event will be triggered.
- *
- * @return The threshold point, in bytes.
- */
- public int getThreshold()
- {
- return threshold;
- }
-
-
- /**
- * Returns the number of bytes that have been written to this output stream.
- *
- * @return The number of bytes written.
- */
- public long getByteCount()
- {
- return written;
- }
-
-
- /**
- * Determines whether or not the configured threshold has been exceeded for
- * this output stream.
- *
- * @return <code>true</code> if the threshold has been reached;
- * <code>false</code> otherwise.
- */
- public boolean isThresholdExceeded()
- {
- return (written > threshold);
- }
-
-
- // ------------------------------------------------------ Protected methods
-
-
- /**
- * Checks to see if writing the specified number of bytes would cause the
- * configured threshold to be exceeded. If so, triggers an event to allow
- * a concrete implementation to take action on this.
- *
- * @param count The number of bytes about to be written to the underlying
- * output stream.
- *
- * @exception IOException if an error occurs.
- */
- protected void checkThreshold(int count) throws IOException
- {
- if (!thresholdExceeded && (written + count > threshold))
- {
- thresholdExceeded = true;
- thresholdReached();
- }
- }
-
- /**
- * Resets the byteCount to zero. You can call this from
- * {@link #thresholdReached()} if you want the event to be triggered again.
- */
- protected void resetByteCount()
- {
- this.thresholdExceeded = false;
- this.written = 0;
- }
-
- // ------------------------------------------------------- Abstract methods
-
-
- /**
- * Returns the underlying output stream, to which the corresponding
- * <code>OutputStream</code> methods in this class will ultimately delegate.
- *
- * @return The underlying output stream.
- *
- * @exception IOException if an error occurs.
- */
- protected abstract OutputStream getStream() throws IOException;
-
-
- /**
- * Indicates that the configured threshold has been reached, and that a
- * subclass should take whatever action necessary on this event. This may
- * include changing the underlying output stream.
- *
- * @exception IOException if an error occurs.
- */
- protected abstract void thresholdReached() throws IOException;
-}
diff --git a/src/org/apache/commons/io/output/package.html b/src/org/apache/commons/io/output/package.html
deleted file mode 100644
index db2cbce59..000000000
--- a/src/org/apache/commons/io/output/package.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<html>
-<body>
-<p>
-This package provides implementations of output classes, such as
-<code>OutputStream</code> and <code>Writer</code>.
-</p>
-</body>
-</html>
diff --git a/src/org/apache/commons/io/overview.html b/src/org/apache/commons/io/overview.html
deleted file mode 100644
index 31311b5e9..000000000
--- a/src/org/apache/commons/io/overview.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<html>
-<body bgcolor="white">
-<p>
-The commons-io component contains utility classes,
-filters, streams, readers and writers.
-</p>
-<p>
-These classes aim to add to the standard JDK IO classes.
-The utilities provide convenience wrappers around the JDK, simplifying
-various operations into pre-tested units of code.
-The filters and streams provide useful implementations that perhaps should
-be in the JDK itself.
-</p>
-</body>
-</html>
diff --git a/src/org/apache/commons/io/package.html b/src/org/apache/commons/io/package.html
deleted file mode 100644
index e5ba9b0aa..000000000
--- a/src/org/apache/commons/io/package.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<html>
-<body bgcolor="white">
-<p>
-This package defines utility classes for working with streams, readers,
-writers and files. The most commonly used classes are described here:
-</p>
-<p>
-<b>IOUtils</b> is the most frequently used class.
-It provides operations to read, write, copy and close streams.
-</p>
-<p>
-<b>FileUtils</b> provides operations based around the JDK File class.
-These include reading, writing, copying, comparing and deleting.
-</p>
-<p>
-<b>FilenameUtils</b> provides utilities based on filenames.
-This utility class manipulates filenames without using File objects.
-It aims to simplify the transition between Windows and Unix.
-Before using this class however, you should consider whether you should
-be using File objects.
-</p>
-<p>
-<b>FileSystemUtils</b> allows access to the filing system in ways the JDK
-does not support. At present this allows you to get the free space on a drive.
-</p>
-<p>
-<b>EndianUtils</b> swaps data between Big-Endian and Little-Endian formats.
-</p>
-</body>
-</html>
diff --git a/src/org/apache/james/mime4j/AbstractContentHandler.java b/src/org/apache/james/mime4j/AbstractContentHandler.java
deleted file mode 100644
index 06c9b90a0..000000000
--- a/src/org/apache/james/mime4j/AbstractContentHandler.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Abstract <code>ContentHandler</code> with default implementations of all
- * the methods of the <code>ContentHandler</code> interface.
- *
- * The default is to todo nothing.
- *
- *
- * @version $Id: AbstractContentHandler.java,v 1.3 2004/10/02 12:41:10 ntherning Exp $
- */
-public abstract class AbstractContentHandler implements ContentHandler {
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#endMultipart()
- */
- public void endMultipart() {
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#startMultipart(org.apache.james.mime4j.BodyDescriptor)
- */
- public void startMultipart(BodyDescriptor bd) {
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#body(org.apache.james.mime4j.BodyDescriptor, java.io.InputStream)
- */
- public void body(BodyDescriptor bd, InputStream is) throws IOException {
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#endBodyPart()
- */
- public void endBodyPart() {
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#endHeader()
- */
- public void endHeader() {
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#endMessage()
- */
- public void endMessage() {
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#epilogue(java.io.InputStream)
- */
- public void epilogue(InputStream is) throws IOException {
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#field(java.lang.String)
- */
- public void field(String fieldData) {
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#preamble(java.io.InputStream)
- */
- public void preamble(InputStream is) throws IOException {
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#startBodyPart()
- */
- public void startBodyPart() {
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#startHeader()
- */
- public void startHeader() {
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#startMessage()
- */
- public void startMessage() {
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#raw(java.io.InputStream)
- */
- public void raw(InputStream is) throws IOException {
- }
-}
diff --git a/src/org/apache/james/mime4j/BodyDescriptor.java b/src/org/apache/james/mime4j/BodyDescriptor.java
deleted file mode 100644
index 515658a8d..000000000
--- a/src/org/apache/james/mime4j/BodyDescriptor.java
+++ /dev/null
@@ -1,410 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Encapsulates the values of the MIME-specific header fields
- * (which starts with <code>Content-</code>).
- *
- *
- * @version $Id: BodyDescriptor.java,v 1.4 2005/02/11 10:08:37 ntherning Exp $
- */
-public class BodyDescriptor {
- private static Log log = LogFactory.getLog(BodyDescriptor.class);
-
- private String mimeType = "text/plain";
- private String boundary = null;
- private String charset = "us-ascii";
- private String transferEncoding = "7bit";
- private Map parameters = new HashMap();
- private boolean contentTypeSet = false;
- private boolean contentTransferEncSet = false;
-
- /**
- * Creates a new root <code>BodyDescriptor</code> instance.
- */
- public BodyDescriptor() {
- this(null);
- }
-
- /**
- * Creates a new <code>BodyDescriptor</code> instance.
- *
- * @param parent the descriptor of the parent or <code>null</code> if this
- * is the root descriptor.
- */
- public BodyDescriptor(BodyDescriptor parent) {
- if (parent != null && parent.isMimeType("multipart/digest")) {
- mimeType = "message/rfc822";
- } else {
- mimeType = "text/plain";
- }
- }
-
- /**
- * Should be called for each <code>Content-</code> header field of
- * a MIME message or part.
- *
- * @param name the field name.
- * @param value the field value.
- */
- public void addField(String name, String value) {
-
- name = name.trim().toLowerCase();
-
- if (name.equals("content-transfer-encoding") && !contentTransferEncSet) {
- contentTransferEncSet = true;
-
- value = value.trim().toLowerCase();
- if (value.length() > 0) {
- transferEncoding = value;
- }
-
- } else if (name.equals("content-type") && !contentTypeSet) {
- contentTypeSet = true;
-
- value = value.trim();
-
- /*
- * Unfold Content-Type value
- */
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < value.length(); i++) {
- char c = value.charAt(i);
- if (c == '\r' || c == '\n') {
- continue;
- }
- sb.append(c);
- }
-
- Map params = getHeaderParams(sb.toString());
-
- String main = (String) params.get("");
- if (main != null) {
- main = main.toLowerCase().trim();
- int index = main.indexOf('/');
- boolean valid = false;
- if (index != -1) {
- String type = main.substring(0, index).trim();
- String subtype = main.substring(index + 1).trim();
- if (type.length() > 0 && subtype.length() > 0) {
- main = type + "/" + subtype;
- valid = true;
- }
- }
-
- if (!valid) {
- main = null;
- }
- }
- String b = (String) params.get("boundary");
-
- if (main != null
- && ((main.startsWith("multipart/") && b != null)
- || !main.startsWith("multipart/"))) {
-
- mimeType = main;
- }
-
- if (isMultipart()) {
- boundary = b;
- }
-
- String c = (String) params.get("charset");
- if (c != null) {
- c = c.trim();
- if (c.length() > 0) {
- charset = c.toLowerCase();
- }
- }
-
- /*
- * Add all other parameters to parameters.
- */
- parameters.putAll(params);
- parameters.remove("");
- parameters.remove("boundary");
- parameters.remove("charset");
- }
- }
-
- private Map getHeaderParams(String headerValue) {
- Map result = new HashMap();
-
- // split main value and parameters
- String main;
- String rest;
- if (headerValue.indexOf(";") == -1) {
- main = headerValue;
- rest = null;
- } else {
- main = headerValue.substring(0, headerValue.indexOf(";"));
- rest = headerValue.substring(main.length() + 1);
- }
-
- result.put("", main);
- if (rest != null) {
- char[] chars = rest.toCharArray();
- StringBuffer paramName = new StringBuffer();
- StringBuffer paramValue = new StringBuffer();
-
- final byte READY_FOR_NAME = 0;
- final byte IN_NAME = 1;
- final byte READY_FOR_VALUE = 2;
- final byte IN_VALUE = 3;
- final byte IN_QUOTED_VALUE = 4;
- final byte VALUE_DONE = 5;
- final byte ERROR = 99;
-
- byte state = READY_FOR_NAME;
- boolean escaped = false;
- for (int i = 0; i < chars.length; i++) {
- char c = chars[i];
-
- switch (state) {
- case ERROR:
- if (c == ';')
- state = READY_FOR_NAME;
- break;
-
- case READY_FOR_NAME:
- if (c == '=') {
- log.error("Expected header param name, got '='");
- state = ERROR;
- break;
- }
-
- paramName = new StringBuffer();
- paramValue = new StringBuffer();
-
- state = IN_NAME;
- // fall-through
-
- case IN_NAME:
- if (c == '=') {
- if (paramName.length() == 0)
- state = ERROR;
- else
- state = READY_FOR_VALUE;
- break;
- }
-
- // not '='... just add to name
- paramName.append(c);
- break;
-
- case READY_FOR_VALUE:
- boolean fallThrough = false;
- switch (c) {
- case ' ':
- case '\t':
- break; // ignore spaces, especially before '"'
-
- case '"':
- state = IN_QUOTED_VALUE;
- break;
-
- default:
- state = IN_VALUE;
- fallThrough = true;
- break;
- }
- if (!fallThrough)
- break;
-
- // fall-through
-
- case IN_VALUE:
- fallThrough = false;
- switch (c) {
- case ';':
- case ' ':
- case '\t':
- result.put(
- paramName.toString().trim().toLowerCase(),
- paramValue.toString().trim());
- state = VALUE_DONE;
- fallThrough = true;
- break;
- default:
- paramValue.append(c);
- break;
- }
- if (!fallThrough)
- break;
-
- case VALUE_DONE:
- switch (c) {
- case ';':
- state = READY_FOR_NAME;
- break;
-
- case ' ':
- case '\t':
- break;
-
- default:
- state = ERROR;
- break;
- }
- break;
-
- case IN_QUOTED_VALUE:
- switch (c) {
- case '"':
- if (!escaped) {
- // don't trim quoted strings; the spaces could be intentional.
- result.put(
- paramName.toString().trim().toLowerCase(),
- paramValue.toString());
- state = VALUE_DONE;
- } else {
- escaped = false;
- paramValue.append(c);
- }
- break;
-
- case '\\':
- if (escaped) {
- paramValue.append('\\');
- }
- escaped = !escaped;
- break;
-
- default:
- if (escaped) {
- paramValue.append('\\');
- }
- escaped = false;
- paramValue.append(c);
- break;
- }
- break;
-
- }
- }
-
- // done looping. check if anything is left over.
- if (state == IN_VALUE) {
- result.put(
- paramName.toString().trim().toLowerCase(),
- paramValue.toString().trim());
- }
- }
-
- return result;
- }
-
-
- public boolean isMimeType(String mimeType) {
- return this.mimeType.equals(mimeType.toLowerCase());
- }
-
- /**
- * Return true if the BodyDescriptor belongs to a message
- *
- * @return
- */
- public boolean isMessage() {
- return mimeType.equals("message/rfc822");
- }
-
- /**
- * Retrun true if the BodyDescripotro belogns to a multipart
- *
- * @return
- */
- public boolean isMultipart() {
- return mimeType.startsWith("multipart/");
- }
-
- /**
- * Return the MimeType
- *
- * @return mimeType
- */
- public String getMimeType() {
- return mimeType;
- }
-
- /**
- * Return the boundary
- *
- * @return boundary
- */
- public String getBoundary() {
- return boundary;
- }
-
- /**
- * Return the charset
- *
- * @return charset
- */
- public String getCharset() {
- return charset;
- }
-
- /**
- * Return all parameters for the BodyDescriptor
- *
- * @return parameters
- */
- public Map getParameters() {
- return parameters;
- }
-
- /**
- * Return the TransferEncoding
- *
- * @return transferEncoding
- */
- public String getTransferEncoding() {
- return transferEncoding;
- }
-
- /**
- * Return true if it's base64 encoded
- *
- * @return
- *
- */
- public boolean isBase64Encoded() {
- return "base64".equals(transferEncoding);
- }
-
- /**
- * Return true if it's quoted-printable
- * @return
- */
- public boolean isQuotedPrintableEncoded() {
- return "quoted-printable".equals(transferEncoding);
- }
-
- public String toString() {
- return mimeType;
- }
-}
diff --git a/src/org/apache/james/mime4j/CloseShieldInputStream.java b/src/org/apache/james/mime4j/CloseShieldInputStream.java
deleted file mode 100644
index 94995d110..000000000
--- a/src/org/apache/james/mime4j/CloseShieldInputStream.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j;
-
-import java.io.InputStream;
-import java.io.IOException;
-
-/**
- * InputStream that shields its underlying input stream from
- * being closed.
- *
- *
- * @version $Id: CloseShieldInputStream.java,v 1.2 2004/10/02 12:41:10 ntherning Exp $
- */
-public class CloseShieldInputStream extends InputStream {
-
- /**
- * Underlying InputStream
- */
- private InputStream is;
-
- public CloseShieldInputStream(InputStream is) {
- this.is = is;
- }
-
- public InputStream getUnderlyingStream() {
- return is;
- }
-
- /**
- * @see java.io.InputStream#read()
- */
- public int read() throws IOException {
- checkIfClosed();
- return is.read();
- }
-
- /**
- * @see java.io.InputStream#available()
- */
- public int available() throws IOException {
- checkIfClosed();
- return is.available();
- }
-
-
- /**
- * Set the underlying InputStream to null
- */
- public void close() throws IOException {
- is = null;
- }
-
- /**
- * @see java.io.FilterInputStream#reset()
- */
- public synchronized void reset() throws IOException {
- checkIfClosed();
- is.reset();
- }
-
- /**
- * @see java.io.FilterInputStream#markSupported()
- */
- public boolean markSupported() {
- if (is == null)
- return false;
- return is.markSupported();
- }
-
- /**
- * @see java.io.FilterInputStream#mark(int)
- */
- public synchronized void mark(int readlimit) {
- if (is != null)
- is.mark(readlimit);
- }
-
- /**
- * @see java.io.FilterInputStream#skip(long)
- */
- public long skip(long n) throws IOException {
- checkIfClosed();
- return is.skip(n);
- }
-
- /**
- * @see java.io.FilterInputStream#read(byte[])
- */
- public int read(byte b[]) throws IOException {
- checkIfClosed();
- return is.read(b);
- }
-
- /**
- * @see java.io.FilterInputStream#read(byte[], int, int)
- */
- public int read(byte b[], int off, int len) throws IOException {
- checkIfClosed();
- return is.read(b, off, len);
- }
-
- /**
- * Check if the underlying InputStream is null. If so throw an Exception
- *
- * @throws IOException if the underlying InputStream is null
- */
- private void checkIfClosed() throws IOException {
- if (is == null)
- throw new IOException("Stream is closed");
- }
-}
diff --git a/src/org/apache/james/mime4j/ContentHandler.java b/src/org/apache/james/mime4j/ContentHandler.java
deleted file mode 100644
index 946c89401..000000000
--- a/src/org/apache/james/mime4j/ContentHandler.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * <p>
- * Receives notifications of the content of a plain RFC822 or MIME message.
- * Implement this interface and register an instance of that implementation
- * with a <code>MimeStreamParser</code> instance using its
- * {@link org.apache.james.mime4j.MimeStreamParser#setContentHandler(ContentHandler)}
- * method. The parser uses the <code>ContentHandler</code> instance to report
- * basic message-related events like the start and end of the body of a
- * part in a multipart MIME entity.
- * </p>
- * <p>
- * Events will be generated in the order the corresponding elements occur in
- * the message stream parsed by the parser. E.g.:
- * <pre>
- * startMessage()
- * startHeader()
- * field(...)
- * field(...)
- * ...
- * endHeader()
- * startMultipart()
- * preamble(...)
- * startBodyPart()
- * startHeader()
- * field(...)
- * field(...)
- * ...
- * endHeader()
- * body()
- * endBodyPart()
- * startBodyPart()
- * startHeader()
- * field(...)
- * field(...)
- * ...
- * endHeader()
- * body()
- * endBodyPart()
- * epilogue(...)
- * endMultipart()
- * endMessage()
- * </pre>
- * The above shows an example of a MIME message consisting of a multipart
- * body containing two body parts.
- * </p>
- * <p>
- * See MIME RFCs 2045-2049 for more information on the structure of MIME
- * messages and RFC 822 and 2822 for the general structure of Internet mail
- * messages.
- * </p>
- *
- *
- * @version $Id: ContentHandler.java,v 1.3 2004/10/02 12:41:10 ntherning Exp $
- */
-public interface ContentHandler {
- /**
- * Called when a new message starts (a top level message or an embedded
- * rfc822 message).
- */
- void startMessage();
-
- /**
- * Called when a message ends.
- */
- void endMessage();
-
- /**
- * Called when a new body part starts inside a
- * <code>multipart/*</code> entity.
- */
- void startBodyPart();
-
- /**
- * Called when a body part ends.
- */
- void endBodyPart();
-
- /**
- * Called when a header (of a message or body part) is about to be parsed.
- */
- void startHeader();
-
- /**
- * Called for each field of a header.
- *
- * @param fieldData the raw contents of the field
- * (<code>Field-Name: field value</code>). The value will not be
- * unfolded.
- */
- void field(String fieldData);
-
- /**
- * Called when there are no more header fields in a message or body part.
- */
- void endHeader();
-
- /**
- * Called for the preamble (whatever comes before the first body part)
- * of a <code>multipart/*</code> entity.
- *
- * @param is used to get the contents of the preamble.
- * @throws IOException should be thrown on I/O errors.
- */
- void preamble(InputStream is) throws IOException;
-
- /**
- * Called for the epilogue (whatever comes after the final body part)
- * of a <code>multipart/*</code> entity.
- *
- * @param is used to get the contents of the epilogue.
- * @throws IOException should be thrown on I/O errors.
- */
- void epilogue(InputStream is) throws IOException;
-
- /**
- * Called when the body of a multipart entity is about to be parsed.
- *
- * @param bd encapsulates the values (either read from the
- * message stream or, if not present, determined implictly
- * as described in the
- * MIME rfc:s) of the <code>Content-Type</code> and
- * <code>Content-Transfer-Encoding</code> header fields.
- */
- void startMultipart(BodyDescriptor bd);
-
- /**
- * Called when the body of an entity has been parsed.
- */
- void endMultipart();
-
- /**
- * Called when the body of a discrete (non-multipart) entity is about to
- * be parsed.
- *
- * @param bd see {@link #startMultipart(BodyDescriptor)}
- * @param is the contents of the body. NOTE: this is the raw body contents
- * - it will not be decoded if encoded. The <code>bd</code>
- * parameter should be used to determine how the stream data
- * should be decoded.
- * @throws IOException should be thrown on I/O errors.
- */
- void body(BodyDescriptor bd, InputStream is) throws IOException;
-
- /**
- * Called when a new entity (message or body part) starts and the
- * parser is in <code>raw</code> mode.
- *
- * @param is the raw contents of the entity.
- * @throws IOException should be thrown on I/O errors.
- * @see MimeStreamParser#setRaw(boolean)
- */
- void raw(InputStream is) throws IOException;
-}
diff --git a/src/org/apache/james/mime4j/EOLConvertingInputStream.java b/src/org/apache/james/mime4j/EOLConvertingInputStream.java
deleted file mode 100644
index 7d5009ca5..000000000
--- a/src/org/apache/james/mime4j/EOLConvertingInputStream.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PushbackInputStream;
-
-/**
- * InputStream which converts <code>\r</code>
- * bytes not followed by <code>\n</code> and <code>\n</code> not
- * preceded by <code>\r</code> to <code>\r\n</code>.
- *
- *
- * @version $Id: EOLConvertingInputStream.java,v 1.4 2004/11/29 13:15:42 ntherning Exp $
- */
-public class EOLConvertingInputStream extends InputStream {
- /** Converts single '\r' to '\r\n' */
- public static final int CONVERT_CR = 1;
- /** Converts single '\n' to '\r\n' */
- public static final int CONVERT_LF = 2;
- /** Converts single '\r' and '\n' to '\r\n' */
- public static final int CONVERT_BOTH = 3;
-
- private PushbackInputStream in = null;
- private int previous = 0;
- private int flags = CONVERT_BOTH;
-
- /**
- * Creates a new <code>EOLConvertingInputStream</code>
- * instance converting bytes in the given <code>InputStream</code>.
- * The flag <code>CONVERT_BOTH</code> is the default.
- *
- * @param in the <code>InputStream</code> to read from.
- */
- public EOLConvertingInputStream(InputStream in) {
- this(in, CONVERT_BOTH);
- }
- /**
- * Creates a new <code>EOLConvertingInputStream</code>
- * instance converting bytes in the given <code>InputStream</code>.
- *
- * @param in the <code>InputStream</code> to read from.
- * @param flags one of <code>CONVERT_CR</code>, <code>CONVERT_LF</code> or
- * <code>CONVERT_BOTH</code>.
- */
- public EOLConvertingInputStream(InputStream in, int flags) {
- super();
-
- this.in = new PushbackInputStream(in, 2);
- this.flags = flags;
- }
-
- /**
- * Closes the underlying stream.
- *
- * @throws IOException on I/O errors.
- */
- public void close() throws IOException {
- in.close();
- }
-
- /**
- * @see java.io.InputStream#read()
- */
- public int read() throws IOException {
- int b = in.read();
-
- if (b == -1) {
- return -1;
- }
-
- if ((flags & CONVERT_CR) != 0 && b == '\r') {
- int c = in.read();
- if (c != -1) {
- in.unread(c);
- }
- if (c != '\n') {
- in.unread('\n');
- }
- } else if ((flags & CONVERT_LF) != 0 && b == '\n' && previous != '\r') {
- b = '\r';
- in.unread('\n');
- }
-
- previous = b;
-
- return b;
- }
-
-}
diff --git a/src/org/apache/james/mime4j/MimeBoundaryInputStream.java b/src/org/apache/james/mime4j/MimeBoundaryInputStream.java
deleted file mode 100644
index 0fffb7820..000000000
--- a/src/org/apache/james/mime4j/MimeBoundaryInputStream.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PushbackInputStream;
-
-/**
- * Stream that constrains itself to a single MIME body part.
- * After the stream ends (i.e. read() returns -1) {@link #hasMoreParts()}
- * can be used to determine if a final boundary has been seen or not.
- * If {@link #parentEOF()} is <code>true</code> an unexpected end of stream
- * has been detected in the parent stream.
- *
- *
- *
- * @version $Id: MimeBoundaryInputStream.java,v 1.2 2004/11/29 13:15:42 ntherning Exp $
- */
-public class MimeBoundaryInputStream extends InputStream {
-
- private PushbackInputStream s = null;
- private byte[] boundary = null;
- private boolean first = true;
- private boolean eof = false;
- private boolean parenteof = false;
- private boolean moreParts = true;
-
- /**
- * Creates a new MimeBoundaryInputStream.
- * @param s The underlying stream.
- * @param boundary Boundary string (not including leading hyphens).
- */
- public MimeBoundaryInputStream(InputStream s, String boundary)
- throws IOException {
-
- this.s = new PushbackInputStream(s, boundary.length() + 4);
-
- boundary = "--" + boundary;
- this.boundary = new byte[boundary.length()];
- for (int i = 0; i < this.boundary.length; i++) {
- this.boundary[i] = (byte) boundary.charAt(i);
- }
-
- /*
- * By reading one byte we will update moreParts to be as expected
- * before any bytes have been read.
- */
- int b = read();
- if (b != -1) {
- this.s.unread(b);
- }
- }
-
- /**
- * Closes the underlying stream.
- *
- * @throws IOException on I/O errors.
- */
- public void close() throws IOException {
- s.close();
- }
-
- /**
- * Determines if the underlying stream has more parts (this stream has
- * not seen an end boundary).
- *
- * @return <code>true</code> if there are more parts in the underlying
- * stream, <code>false</code> otherwise.
- */
- public boolean hasMoreParts() {
- return moreParts;
- }
-
- /**
- * Determines if the parent stream has reached EOF
- *
- * @return <code>true</code> if EOF has been reached for the parent stream,
- * <code>false</code> otherwise.
- */
- public boolean parentEOF() {
- return parenteof;
- }
-
- /**
- * Consumes all unread bytes of this stream. After a call to this method
- * this stream will have reached EOF.
- *
- * @throws IOException on I/O errors.
- */
- public void consume() throws IOException {
- while (read() != -1) {
- }
- }
-
- /**
- * @see java.io.InputStream#read()
- */
- public int read() throws IOException {
- if (eof) {
- return -1;
- }
-
- if (first) {
- first = false;
- if (matchBoundary()) {
- return -1;
- }
- }
-
- int b1 = s.read();
- int b2 = s.read();
-
- if (b1 == '\r' && b2 == '\n') {
- if (matchBoundary()) {
- return -1;
- }
- }
-
- if (b2 != -1) {
- s.unread(b2);
- }
-
- parenteof = b1 == -1;
- eof = parenteof;
-
- return b1;
- }
-
- private boolean matchBoundary() throws IOException {
-
- for (int i = 0; i < boundary.length; i++) {
- int b = s.read();
- if (b != boundary[i]) {
- if (b != -1) {
- s.unread(b);
- }
- for (int j = i - 1; j >= 0; j--) {
- s.unread(boundary[j]);
- }
- return false;
- }
- }
-
- /*
- * We have a match. Is it an end boundary?
- */
- int prev = s.read();
- int curr = s.read();
- moreParts = !(prev == '-' && curr == '-');
- do {
- if (curr == '\n' && prev == '\r') {
- break;
- }
- prev = curr;
- } while ((curr = s.read()) != -1);
-
- if (curr == -1) {
- moreParts = false;
- parenteof = true;
- }
-
- eof = true;
-
- return true;
- }
-}
diff --git a/src/org/apache/james/mime4j/MimeStreamParser.java b/src/org/apache/james/mime4j/MimeStreamParser.java
deleted file mode 100644
index 2e486adc3..000000000
--- a/src/org/apache/james/mime4j/MimeStreamParser.java
+++ /dev/null
@@ -1,320 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.BitSet;
-import java.util.LinkedList;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.james.mime4j.decoder.Base64InputStream;
-import org.apache.james.mime4j.decoder.QuotedPrintableInputStream;
-
-/**
- * <p>
- * Parses MIME (or RFC822) message streams of bytes or characters and reports
- * parsing events to a <code>ContentHandler</code> instance.
- * </p>
- * <p>
- * Typical usage:<br/>
- * <pre>
- * ContentHandler handler = new MyHandler();
- * MimeStreamParser parser = new MimeStreamParser();
- * parser.setContentHandler(handler);
- * parser.parse(new BufferedInputStream(new FileInputStream("mime.msg")));
- * </pre>
- * <strong>NOTE:</strong> All lines must end with CRLF
- * (<code>\r\n</code>). If you are unsure of the line endings in your stream
- * you should wrap it in a {@link org.apache.james.mime4j.EOLConvertingInputStream} instance.
- *
- *
- * @version $Id: MimeStreamParser.java,v 1.8 2005/02/11 10:12:02 ntherning Exp $
- */
-public class MimeStreamParser {
- private static final Log log = LogFactory.getLog(MimeStreamParser.class);
-
- private static BitSet fieldChars = null;
-
- private RootInputStream rootStream = null;
- private LinkedList bodyDescriptors = new LinkedList();
- private ContentHandler handler = null;
- private boolean raw = false;
-
- static {
- fieldChars = new BitSet();
- for (int i = 0x21; i <= 0x39; i++) {
- fieldChars.set(i);
- }
- for (int i = 0x3b; i <= 0x7e; i++) {
- fieldChars.set(i);
- }
- }
-
- /**
- * Creates a new <code>MimeStreamParser</code> instance.
- */
- public MimeStreamParser() {
- }
-
- /**
- * Parses a stream of bytes containing a MIME message.
- *
- * @param is the stream to parse.
- * @throws IOException on I/O errors.
- */
- public void parse(InputStream is) throws IOException {
- rootStream = new RootInputStream(is);
- parseMessage(rootStream);
- }
-
- /**
- * Determines if this parser is currently in raw mode.
- *
- * @return <code>true</code> if in raw mode, <code>false</code>
- * otherwise.
- * @see #setRaw(boolean)
- */
- public boolean isRaw() {
- return raw;
- }
-
- /**
- * Enables or disables raw mode. In raw mode all future entities
- * (messages or body parts) in the stream will be reported to the
- * {@link ContentHandler#raw(InputStream)} handler method only.
- * The stream will contain the entire unparsed entity contents
- * including header fields and whatever is in the body.
- *
- * @param raw <code>true</code> enables raw mode, <code>false</code>
- * disables it.
- */
- public void setRaw(boolean raw) {
- this.raw = raw;
- }
-
- /**
- * Finishes the parsing and stops reading lines.
- * NOTE: No more lines will be parsed but the parser
- * will still call
- * {@link ContentHandler#endMultipart()},
- * {@link ContentHandler#endBodyPart()},
- * {@link ContentHandler#endMessage()}, etc to match previous calls
- * to
- * {@link ContentHandler#startMultipart(BodyDescriptor)},
- * {@link ContentHandler#startBodyPart()},
- * {@link ContentHandler#startMessage()}, etc.
- */
- public void stop() {
- rootStream.truncate();
- }
-
- /**
- * Parses an entity which consists of a header followed by a body containing
- * arbitrary data, body parts or an embedded message.
- *
- * @param is the stream to parse.
- * @throws IOException on I/O errors.
- */
- private void parseEntity(InputStream is) throws IOException {
- BodyDescriptor bd = parseHeader(is);
-
- if (bd.isMultipart()) {
- bodyDescriptors.addFirst(bd);
-
- handler.startMultipart(bd);
-
- MimeBoundaryInputStream tempIs =
- new MimeBoundaryInputStream(is, bd.getBoundary());
- handler.preamble(new CloseShieldInputStream(tempIs));
- tempIs.consume();
-
- while (tempIs.hasMoreParts()) {
- tempIs = new MimeBoundaryInputStream(is, bd.getBoundary());
- parseBodyPart(tempIs);
- tempIs.consume();
- if (tempIs.parentEOF()) {
- if (log.isWarnEnabled()) {
- log.warn("Line " + rootStream.getLineNumber()
- + ": Body part ended prematurely. "
- + "Higher level boundary detected or "
- + "EOF reached.");
- }
- break;
- }
- }
-
- handler.epilogue(new CloseShieldInputStream(is));
-
- handler.endMultipart();
-
- bodyDescriptors.removeFirst();
-
- } else if (bd.isMessage()) {
- if (bd.isBase64Encoded()) {
- log.warn("base64 encoded message/rfc822 detected");
- is = new EOLConvertingInputStream(
- new Base64InputStream(is));
- } else if (bd.isQuotedPrintableEncoded()) {
- log.warn("quoted-printable encoded message/rfc822 detected");
- is = new EOLConvertingInputStream(
- new QuotedPrintableInputStream(is));
- }
- bodyDescriptors.addFirst(bd);
- parseMessage(is);
- bodyDescriptors.removeFirst();
- } else {
- handler.body(bd, new CloseShieldInputStream(is));
- }
-
- /*
- * Make sure the stream has been consumed.
- */
- while (is.read() != -1) {
- }
- }
-
- private void parseMessage(InputStream is) throws IOException {
- if (raw) {
- handler.raw(new CloseShieldInputStream(is));
- } else {
- handler.startMessage();
- parseEntity(is);
- handler.endMessage();
- }
- }
-
- private void parseBodyPart(InputStream is) throws IOException {
- if (raw) {
- handler.raw(new CloseShieldInputStream(is));
- } else {
- handler.startBodyPart();
- parseEntity(is);
- handler.endBodyPart();
- }
- }
-
- /**
- * Parses a header.
- *
- * @param is the stream to parse.
- * @return a <code>BodyDescriptor</code> describing the body following
- * the header.
- */
- private BodyDescriptor parseHeader(InputStream is) throws IOException {
- BodyDescriptor bd = new BodyDescriptor(bodyDescriptors.isEmpty()
- ? null : (BodyDescriptor) bodyDescriptors.getFirst());
-
- handler.startHeader();
-
- int lineNumber = rootStream.getLineNumber();
-
- StringBuffer sb = new StringBuffer();
- int curr = 0;
- int prev = 0;
- while ((curr = is.read()) != -1) {
- if (curr == '\n' && (prev == '\n' || prev == 0)) {
- /*
- * [\r]\n[\r]\n or an immediate \r\n have been seen.
- */
- sb.deleteCharAt(sb.length() - 1);
- break;
- }
- sb.append((char) curr);
- prev = curr == '\r' ? prev : curr;
- }
-
- if (curr == -1 && log.isWarnEnabled()) {
- log.warn("Line " + rootStream.getLineNumber()
- + ": Unexpected end of headers detected. "
- + "Boundary detected in header or EOF reached.");
- }
-
- int start = 0;
- int pos = 0;
- int startLineNumber = lineNumber;
- while (pos < sb.length()) {
- while (pos < sb.length() && sb.charAt(pos) != '\r') {
- pos++;
- }
- if (pos < sb.length() - 1 && sb.charAt(pos + 1) != '\n') {
- pos++;
- continue;
- }
-
- if (pos >= sb.length() - 2 || fieldChars.get(sb.charAt(pos + 2))) {
-
- /*
- * field should be the complete field data excluding the
- * trailing \r\n.
- */
- String field = sb.substring(start, pos);
- start = pos + 2;
-
- /*
- * Check for a valid field.
- */
- int index = field.indexOf(':');
- boolean valid = false;
- if (index != -1 && fieldChars.get(field.charAt(0))) {
- valid = true;
- String fieldName = field.substring(0, index).trim();
- for (int i = 0; i < fieldName.length(); i++) {
- if (!fieldChars.get(fieldName.charAt(i))) {
- valid = false;
- break;
- }
- }
-
- if (valid) {
- handler.field(field);
- bd.addField(fieldName, field.substring(index + 1));
- }
- }
-
- if (!valid && log.isWarnEnabled()) {
- log.warn("Line " + startLineNumber
- + ": Ignoring invalid field: '" + field.trim() + "'");
- }
-
- startLineNumber = lineNumber;
- }
-
- pos += 2;
- lineNumber++;
- }
-
- handler.endHeader();
-
- return bd;
- }
-
- /**
- * Sets the <code>ContentHandler</code> to use when reporting
- * parsing events.
- *
- * @param h the <code>ContentHandler</code>.
- */
- public void setContentHandler(ContentHandler h) {
- this.handler = h;
- }
-
-}
diff --git a/src/org/apache/james/mime4j/RootInputStream.java b/src/org/apache/james/mime4j/RootInputStream.java
deleted file mode 100644
index fa848df18..000000000
--- a/src/org/apache/james/mime4j/RootInputStream.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * <code>InputStream</code> used by the parser to wrap the original user
- * supplied stream. This stream keeps track of the current line number and
- * can also be truncated. When truncated the stream will appear to have
- * reached end of file. This is used by the parser's
- * {@link org.apache.james.mime4j.MimeStreamParser#stop()} method.
- *
- *
- * @version $Id: RootInputStream.java,v 1.2 2004/10/02 12:41:10 ntherning Exp $
- */
-class RootInputStream extends InputStream {
- private InputStream is = null;
- private int lineNumber = 1;
- private int prev = -1;
- private boolean truncated = false;
-
- /**
- * Creates a new <code>RootInputStream</code>.
- *
- * @param in the stream to read from.
- */
- public RootInputStream(InputStream is) {
- this.is = is;
- }
-
- /**
- * Gets the current line number starting at 1
- * (the number of <code>\r\n</code> read so far plus 1).
- *
- * @return the current line number.
- */
- public int getLineNumber() {
- return lineNumber;
- }
-
- /**
- * Truncates this <code>InputStream</code>. After this call any
- * call to {@link #read()}, {@link #read(byte[]) or
- * {@link #read(byte[], int, int)} will return
- * -1 as if end-of-file had been reached.
- */
- public void truncate() {
- this.truncated = true;
- }
-
- /**
- * @see java.io.InputStream#read()
- */
- public int read() throws IOException {
- if (truncated) {
- return -1;
- }
-
- int b = is.read();
- if (prev == '\r' && b == '\n') {
- lineNumber++;
- }
- prev = b;
- return b;
- }
-
- /**
- *
- * @see java.io.InputStream#read(byte[], int, int)
- */
- public int read(byte[] b, int off, int len) throws IOException {
- if (truncated) {
- return -1;
- }
-
- int n = is.read(b, off, len);
- for (int i = off; i < off + n; i++) {
- if (prev == '\r' && b[i] == '\n') {
- lineNumber++;
- }
- prev = b[i];
- }
- return n;
- }
-
- /**
- * @see java.io.InputStream#read(byte[])
- */
- public int read(byte[] b) throws IOException {
- return read(b, 0, b.length);
- }
-}
diff --git a/src/org/apache/james/mime4j/SimpleContentHandler.java b/src/org/apache/james/mime4j/SimpleContentHandler.java
deleted file mode 100644
index 13f1fd2c6..000000000
--- a/src/org/apache/james/mime4j/SimpleContentHandler.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j;
-
-import org.apache.james.mime4j.decoder.Base64InputStream;
-import org.apache.james.mime4j.decoder.QuotedPrintableInputStream;
-import org.apache.james.mime4j.field.Field;
-import org.apache.james.mime4j.message.Header;
-
-import java.io.InputStream;
-import java.io.IOException;
-
-/**
- * Abstract implementation of ContentHandler that automates common
- * tasks. Currently performs header parsing and applies content-transfer
- * decoding to body parts.
- *
- *
- */
-public abstract class SimpleContentHandler extends AbstractContentHandler {
-
- /**
- * Called after headers are parsed.
- */
- public abstract void headers(Header header);
-
- /**
- * Called when the body of a discrete (non-multipart) entity is encountered.
-
- * @param bd encapsulates the values (either read from the
- * message stream or, if not present, determined implictly
- * as described in the
- * MIME rfc:s) of the <code>Content-Type</code> and
- * <code>Content-Transfer-Encoding</code> header fields.
- * @param is the contents of the body. Base64 or quoted-printable
- * decoding will be applied transparently.
- * @throws IOException should be thrown on I/O errors.
- */
- public abstract void bodyDecoded(BodyDescriptor bd, InputStream is) throws IOException;
-
-
- /* Implement introduced callbacks. */
-
- private Header currHeader;
-
- /**
- * @see org.apache.james.mime4j.AbstractContentHandler#startHeader()
- */
- public final void startHeader() {
- currHeader = new Header();
- }
-
- /**
- * @see org.apache.james.mime4j.AbstractContentHandler#field(java.lang.String)
- */
- public final void field(String fieldData) {
- currHeader.addField(Field.parse(fieldData));
- }
-
- /**
- * @see org.apache.james.mime4j.AbstractContentHandler#endHeader()
- */
- public final void endHeader() {
- Header tmp = currHeader;
- currHeader = null;
- headers(tmp);
- }
-
- /**
- * @see org.apache.james.mime4j.AbstractContentHandler#body(org.apache.james.mime4j.BodyDescriptor, java.io.InputStream)
- */
- public final void body(BodyDescriptor bd, InputStream is) throws IOException {
- if (bd.isBase64Encoded()) {
- bodyDecoded(bd, new Base64InputStream(is));
- }
- else if (bd.isQuotedPrintableEncoded()) {
- bodyDecoded(bd, new QuotedPrintableInputStream(is));
- }
- else {
- bodyDecoded(bd, is);
- }
- }
-}
diff --git a/src/org/apache/james/mime4j/decoder/Base64InputStream.java b/src/org/apache/james/mime4j/decoder/Base64InputStream.java
deleted file mode 100644
index 930b982c4..000000000
--- a/src/org/apache/james/mime4j/decoder/Base64InputStream.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.decoder;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Performs Base-64 decoding on an underlying stream.
- *
- *
- * @version $Id: Base64InputStream.java,v 1.3 2004/11/29 13:15:47 ntherning Exp $
- */
-public class Base64InputStream extends InputStream {
- private static Log log = LogFactory.getLog(Base64InputStream.class);
-
- private final InputStream s;
- private final ByteQueue byteq = new ByteQueue(3);
- private boolean done = false;
-
- public Base64InputStream(InputStream s) {
- this.s = s;
- }
-
- /**
- * Closes the underlying stream.
- *
- * @throws IOException on I/O errors.
- */
- public void close() throws IOException {
- s.close();
- }
-
- public int read() throws IOException {
- if (byteq.count() == 0) {
- fillBuffer();
- if (byteq.count() == 0) {
- return -1;
- }
- }
-
- byte val = byteq.dequeue();
- if (val >= 0)
- return val;
- else
- return val & 0xFF;
- }
-
- /**
- * Retrieve data from the underlying stream, decode it,
- * and put the results in the byteq.
- * @throws IOException
- */
- private void fillBuffer() throws IOException {
- byte[] data = new byte[4];
- int pos = 0;
-
- int i;
- while (!done) {
- switch (i = s.read()) {
- case -1:
- if (pos > 0) {
- log.warn("Unexpected EOF in MIME parser, dropping "
- + pos + " sextets");
- }
- return;
- case '=':
- decodeAndEnqueue(data, pos);
- done = true;
- break;
- default:
- byte sX = TRANSLATION[i];
- if (sX < 0)
- continue;
- data[pos++] = sX;
- if (pos == data.length) {
- decodeAndEnqueue(data, pos);
- return;
- }
- break;
- }
- }
- }
-
- private void decodeAndEnqueue(byte[] data, int len) {
- int accum = 0;
- accum |= data[0] << 18;
- accum |= data[1] << 12;
- accum |= data[2] << 6;
- accum |= data[3];
-
- byte b1 = (byte)(accum >>> 16);
- byteq.enqueue(b1);
-
- if (len > 2) {
- byte b2 = (byte)((accum >>> 8) & 0xFF);
- byteq.enqueue(b2);
-
- if (len > 3) {
- byte b3 = (byte)(accum & 0xFF);
- byteq.enqueue(b3);
- }
- }
- }
-
- private static byte[] TRANSLATION = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00 */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10 */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20 */
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 0x30 */
- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40 */
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50 */
- -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60 */
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 0x70 */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80 */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90 */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xA0 */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xB0 */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xC0 */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xD0 */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xE0 */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xF0 */
- };
-
-
-}
diff --git a/src/org/apache/james/mime4j/decoder/ByteQueue.java b/src/org/apache/james/mime4j/decoder/ByteQueue.java
deleted file mode 100644
index 68e7d3380..000000000
--- a/src/org/apache/james/mime4j/decoder/ByteQueue.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.decoder;
-
-import java.util.Iterator;
-
-public class ByteQueue {
-
- private UnboundedFifoByteBuffer buf;
- private int initialCapacity = -1;
-
- public ByteQueue() {
- buf = new UnboundedFifoByteBuffer();
- }
-
- public ByteQueue(int initialCapacity) {
- buf = new UnboundedFifoByteBuffer(initialCapacity);
- this.initialCapacity = initialCapacity;
- }
-
- public void enqueue(byte b) {
- buf.add(b);
- }
-
- public byte dequeue() {
- return buf.remove();
- }
-
- public int count() {
- return buf.size();
- }
-
- public void clear() {
- if (initialCapacity != -1)
- buf = new UnboundedFifoByteBuffer(initialCapacity);
- else
- buf = new UnboundedFifoByteBuffer();
- }
-
- public Iterator iterator() {
- return buf.iterator();
- }
-
-
-}
diff --git a/src/org/apache/james/mime4j/decoder/DecoderUtil.java b/src/org/apache/james/mime4j/decoder/DecoderUtil.java
deleted file mode 100644
index 9bd2c512d..000000000
--- a/src/org/apache/james/mime4j/decoder/DecoderUtil.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.decoder;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.james.mime4j.util.CharsetUtil;
-
-/**
- * Static methods for decoding strings, byte arrays and encoded words.
- *
- *
- * @version $Id: DecoderUtil.java,v 1.3 2005/02/07 15:33:59 ntherning Exp $
- */
-public class DecoderUtil {
- private static Log log = LogFactory.getLog(DecoderUtil.class);
-
- /**
- * Decodes a string containing quoted-printable encoded data.
- *
- * @param s the string to decode.
- * @return the decoded bytes.
- */
- public static byte[] decodeBaseQuotedPrintable(String s) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- try {
- byte[] bytes = s.getBytes("US-ASCII");
-
- QuotedPrintableInputStream is = new QuotedPrintableInputStream(
- new ByteArrayInputStream(bytes));
-
- int b = 0;
- while ((b = is.read()) != -1) {
- baos.write(b);
- }
- } catch (IOException e) {
- /*
- * This should never happen!
- */
- log.error(e);
- }
-
- return baos.toByteArray();
- }
-
- /**
- * Decodes a string containing base64 encoded data.
- *
- * @param s the string to decode.
- * @return the decoded bytes.
- */
- public static byte[] decodeBase64(String s) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- try {
- byte[] bytes = s.getBytes("US-ASCII");
-
- Base64InputStream is = new Base64InputStream(
- new ByteArrayInputStream(bytes));
-
- int b = 0;
- while ((b = is.read()) != -1) {
- baos.write(b);
- }
- } catch (IOException e) {
- /*
- * This should never happen!
- */
- log.error(e);
- }
-
- return baos.toByteArray();
- }
-
- /**
- * Decodes an encoded word encoded with the 'B' encoding (described in
- * RFC 2047) found in a header field body.
- *
- * @param encodedWord the encoded word to decode.
- * @param charset the Java charset to use.
- * @return the decoded string.
- * @throws UnsupportedEncodingException if the given Java charset isn't
- * supported.
- */
- public static String decodeB(String encodedWord, String charset)
- throws UnsupportedEncodingException {
-
- return new String(decodeBase64(encodedWord), charset);
- }
-
- /**
- * Decodes an encoded word encoded with the 'Q' encoding (described in
- * RFC 2047) found in a header field body.
- *
- * @param encodedWord the encoded word to decode.
- * @param charset the Java charset to use.
- * @return the decoded string.
- * @throws UnsupportedEncodingException if the given Java charset isn't
- * supported.
- */
- public static String decodeQ(String encodedWord, String charset)
- throws UnsupportedEncodingException {
-
- /*
- * Replace _ with =20
- */
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < encodedWord.length(); i++) {
- char c = encodedWord.charAt(i);
- if (c == '_') {
- sb.append("=20");
- } else {
- sb.append(c);
- }
- }
-
- return new String(decodeBaseQuotedPrintable(sb.toString()), charset);
- }
-
- /**
- * Decodes a string containing encoded words as defined by RFC 2047.
- * Encoded words in have the form
- * =?charset?enc?Encoded word?= where enc is either 'Q' or 'q' for
- * quoted-printable and 'B' or 'b' for Base64.
- *
- * @param body the string to decode.
- * @return the decoded string.
- */
- public static String decodeEncodedWords(String body) {
- StringBuffer sb = new StringBuffer();
-
- int p1 = 0;
- int p2 = 0;
-
- try {
-
- /*
- * Encoded words in headers have the form
- * =?charset?enc?Encoded word?= where enc is either 'Q' or 'q' for
- * quoted printable and 'B' and 'b' for Base64
- */
-
- while (p2 < body.length()) {
- /*
- * Find beginning of first encoded word
- */
- p1 = body.indexOf("=?", p2);
- if (p1 == -1) {
- /*
- * None found. Emit the rest of the header and exit.
- */
- sb.append(body.substring(p2));
- break;
- }
-
- /*
- * p2 points to the previously found end marker or the start
- * of the entire header text. Append the text between that
- * marker and the one pointed to by p1.
- */
- if (p1 - p2 > 0) {
- sb.append(body.substring(p2, p1));
- }
-
- /*
- * Find the first and second '?':s after the marker pointed to
- * by p1.
- */
- int t1 = body.indexOf('?', p1 + 2);
- int t2 = t1 != -1 ? body.indexOf('?', t1 + 1) : -1;
-
- /*
- * Find this words end marker.
- */
- p2 = t2 != -1 ? body.indexOf("?=", t2 + 1) : -1;
- if (p2 == -1) {
- if (t2 != -1 && (body.length() - 1 == t2 || body.charAt(t2 + 1) == '=')) {
- /*
- * Treat "=?charset?enc?" and "=?charset?enc?=" as
- * empty strings.
- */
- p2 = t2;
- } else {
- /*
- * No end marker was found. Append the rest of the
- * header and exit.
- */
- sb.append(body.substring(p1));
- break;
- }
- }
-
- /*
- * [p1+2, t1] -> charset
- * [t1+1, t2] -> encoding
- * [t2+1, p2] -> encoded word
- */
-
- String decodedWord = null;
- if (t2 == p2) {
- /*
- * The text is empty
- */
- decodedWord = "";
- } else {
-
- String mimeCharset = body.substring(p1 + 2, t1);
- String enc = body.substring(t1 + 1, t2);
- String encodedWord = body.substring(t2 + 1, p2);
-
- /*
- * Convert the MIME charset to a corresponding Java one.
- */
- String charset = CharsetUtil.toJavaCharset(mimeCharset);
- if (charset == null) {
- decodedWord = body.substring(p1, p2 + 2);
- if (log.isWarnEnabled()) {
- log.warn("MIME charset '" + mimeCharset
- + "' in header field doesn't have a "
- +"corresponding Java charset");
- }
- } else if (!CharsetUtil.isDecodingSupported(charset)) {
- decodedWord = body.substring(p1, p2 + 2);
- if (log.isWarnEnabled()) {
- log.warn("Current JDK doesn't support decoding "
- + "of charset '" + charset
- + "' (MIME charset '"
- + mimeCharset + "')");
- }
- } else {
- if (enc.equalsIgnoreCase("Q")) {
- decodedWord = DecoderUtil.decodeQ(encodedWord, charset);
- } else if (enc.equalsIgnoreCase("B")) {
- decodedWord = DecoderUtil.decodeB(encodedWord, charset);
- } else {
- decodedWord = encodedWord;
- if (log.isWarnEnabled()) {
- log.warn("Warning: Unknown encoding in "
- + "header field '" + enc + "'");
- }
- }
- }
- }
- p2 += 2;
- sb.append(decodedWord);
- }
- } catch (Throwable t) {
- log.error("Decoding header field body '" + body + "'", t);
- }
-
- return sb.toString();
- }
-}
diff --git a/src/org/apache/james/mime4j/decoder/QuotedPrintableInputStream.java b/src/org/apache/james/mime4j/decoder/QuotedPrintableInputStream.java
deleted file mode 100644
index eb3f09c9a..000000000
--- a/src/org/apache/james/mime4j/decoder/QuotedPrintableInputStream.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.decoder;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Performs Quoted-Printable decoding on an underlying stream.
- *
- *
- *
- * @version $Id: QuotedPrintableInputStream.java,v 1.3 2004/11/29 13:15:47 ntherning Exp $
- */
-public class QuotedPrintableInputStream extends InputStream {
- private static Log log = LogFactory.getLog(QuotedPrintableInputStream.class);
-
- private InputStream stream;
- ByteQueue byteq = new ByteQueue();
- ByteQueue pushbackq = new ByteQueue();
- private byte state = 0;
-
- public QuotedPrintableInputStream(InputStream stream) {
- this.stream = stream;
- }
-
- /**
- * Closes the underlying stream.
- *
- * @throws IOException on I/O errors.
- */
- public void close() throws IOException {
- stream.close();
- }
-
- public int read() throws IOException {
- fillBuffer();
- if (byteq.count() == 0)
- return -1;
- else {
- byte val = byteq.dequeue();
- if (val >= 0)
- return val;
- else
- return val & 0xFF;
- }
- }
-
- /**
- * Pulls bytes out of the underlying stream and places them in the
- * pushback queue. This is necessary (vs. reading from the
- * underlying stream directly) to detect and filter out "transport
- * padding" whitespace, i.e., all whitespace that appears immediately
- * before a CRLF.
- *
- * @throws IOException Underlying stream threw IOException.
- */
- private void populatePushbackQueue() throws IOException {
- //Debug.verify(pushbackq.count() == 0, "PopulatePushbackQueue called when pushback queue was not empty!");
-
- if (pushbackq.count() != 0)
- return;
-
- while (true) {
- int i = stream.read();
- switch (i) {
- case -1:
- // stream is done
- pushbackq.clear(); // discard any whitespace preceding EOF
- return;
- case ' ':
- case '\t':
- pushbackq.enqueue((byte)i);
- break;
- case '\r':
- case '\n':
- pushbackq.clear(); // discard any whitespace preceding EOL
- pushbackq.enqueue((byte)i);
- return;
- default:
- pushbackq.enqueue((byte)i);
- return;
- }
- }
- }
-
- /**
- * Causes the pushback queue to get populated if it is empty, then
- * consumes and decodes bytes out of it until one or more bytes are
- * in the byte queue. This decoding step performs the actual QP
- * decoding.
- *
- * @throws IOException Underlying stream threw IOException.
- */
- private void fillBuffer() throws IOException {
- byte msdChar = 0; // first digit of escaped num
- while (byteq.count() == 0) {
- if (pushbackq.count() == 0) {
- populatePushbackQueue();
- if (pushbackq.count() == 0)
- return;
- }
-
- byte b = (byte)pushbackq.dequeue();
-
- switch (state) {
- case 0: // start state, no bytes pending
- if (b != '=') {
- byteq.enqueue(b);
- break; // state remains 0
- } else {
- state = 1;
- break;
- }
- case 1: // encountered "=" so far
- if (b == '\r') {
- state = 2;
- break;
- } else if ((b >= '0' && b <= '9') || (b >= 'A' && b <= 'F') || (b >= 'a' && b <= 'f')) {
- state = 3;
- msdChar = b; // save until next digit encountered
- break;
- } else if (b == '=') {
- /*
- * Special case when == is encountered.
- * Emit one = and stay in this state.
- */
- if (log.isWarnEnabled()) {
- log.warn("Malformed MIME; got ==");
- }
- byteq.enqueue((byte)'=');
- break;
- } else {
- if (log.isWarnEnabled()) {
- log.warn("Malformed MIME; expected \\r or "
- + "[0-9A-Z], got " + b);
- }
- state = 0;
- byteq.enqueue((byte)'=');
- byteq.enqueue(b);
- break;
- }
- case 2: // encountered "=\r" so far
- if (b == '\n') {
- state = 0;
- break;
- } else {
- if (log.isWarnEnabled()) {
- log.warn("Malformed MIME; expected "
- + (int)'\n' + ", got " + b);
- }
- state = 0;
- byteq.enqueue((byte)'=');
- byteq.enqueue((byte)'\r');
- byteq.enqueue(b);
- break;
- }
- case 3: // encountered =<digit> so far; expecting another <digit> to complete the octet
- if ((b >= '0' && b <= '9') || (b >= 'A' && b <= 'F') || (b >= 'a' && b <= 'f')) {
- byte msd = asciiCharToNumericValue(msdChar);
- byte low = asciiCharToNumericValue(b);
- state = 0;
- byteq.enqueue((byte)((msd << 4) | low));
- break;
- } else {
- if (log.isWarnEnabled()) {
- log.warn("Malformed MIME; expected "
- + "[0-9A-Z], got " + b);
- }
- state = 0;
- byteq.enqueue((byte)'=');
- byteq.enqueue(msdChar);
- byteq.enqueue(b);
- break;
- }
- default: // should never happen
- log.error("Illegal state: " + state);
- state = 0;
- byteq.enqueue(b);
- break;
- }
- }
- }
-
- /**
- * Converts '0' => 0, 'A' => 10, etc.
- * @param c ASCII character value.
- * @return Numeric value of hexadecimal character.
- */
- private byte asciiCharToNumericValue(byte c) {
- if (c >= '0' && c <= '9') {
- return (byte)(c - '0');
- } else if (c >= 'A' && c <= 'Z') {
- return (byte)(0xA + (c - 'A'));
- } else if (c >= 'a' && c <= 'z') {
- return (byte)(0xA + (c - 'a'));
- } else {
- /*
- * This should never happen since all calls to this method
- * are preceded by a check that c is in [0-9A-Za-z]
- */
- throw new IllegalArgumentException((char) c
- + " is not a hexadecimal digit");
- }
- }
-
-}
diff --git a/src/org/apache/james/mime4j/decoder/UnboundedFifoByteBuffer.java b/src/org/apache/james/mime4j/decoder/UnboundedFifoByteBuffer.java
deleted file mode 100644
index dc32caf36..000000000
--- a/src/org/apache/james/mime4j/decoder/UnboundedFifoByteBuffer.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.decoder;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-/**
- * UnboundedFifoByteBuffer is a very efficient buffer implementation.
- * According to performance testing, it exhibits a constant access time, but it
- * also outperforms ArrayList when used for the same purpose.
- * <p>
- * The removal order of an <code>UnboundedFifoByteBuffer</code> is based on the insertion
- * order; elements are removed in the same order in which they were added.
- * The iteration order is the same as the removal order.
- * <p>
- * The {@link #remove()} and {@link #get()} operations perform in constant time.
- * The {@link #add(Object)} operation performs in amortized constant time. All
- * other operations perform in linear time or worse.
- * <p>
- * Note that this implementation is not synchronized. The following can be
- * used to provide synchronized access to your <code>UnboundedFifoByteBuffer</code>:
- * <pre>
- * Buffer fifo = BufferUtils.synchronizedBuffer(new UnboundedFifoByteBuffer());
- * </pre>
- * <p>
- * This buffer prevents null objects from being added.
- *
- * @since Commons Collections 3.0 (previously in main package v2.1)
- * @version $Revision: 1.1 $ $Date: 2004/08/24 06:52:02 $
- *
- *
- *
- *
- *
- *
- */
-class UnboundedFifoByteBuffer {
-
- protected byte[] buffer;
- protected int head;
- protected int tail;
-
- /**
- * Constructs an UnboundedFifoByteBuffer with the default number of elements.
- * It is exactly the same as performing the following:
- *
- * <pre>
- * new UnboundedFifoByteBuffer(32);
- * </pre>
- */
- public UnboundedFifoByteBuffer() {
- this(32);
- }
-
- /**
- * Constructs an UnboundedFifoByteBuffer with the specified number of elements.
- * The integer must be a positive integer.
- *
- * @param initialSize the initial size of the buffer
- * @throws IllegalArgumentException if the size is less than 1
- */
- public UnboundedFifoByteBuffer(int initialSize) {
- if (initialSize <= 0) {
- throw new IllegalArgumentException("The size must be greater than 0");
- }
- buffer = new byte[initialSize + 1];
- head = 0;
- tail = 0;
- }
-
- /**
- * Returns the number of elements stored in the buffer.
- *
- * @return this buffer's size
- */
- public int size() {
- int size = 0;
-
- if (tail < head) {
- size = buffer.length - head + tail;
- } else {
- size = tail - head;
- }
-
- return size;
- }
-
- /**
- * Returns true if this buffer is empty; false otherwise.
- *
- * @return true if this buffer is empty
- */
- public boolean isEmpty() {
- return (size() == 0);
- }
-
- /**
- * Adds the given element to this buffer.
- *
- * @param b the byte to add
- * @return true, always
- */
- public boolean add(final byte b) {
-
- if (size() + 1 >= buffer.length) {
- byte[] tmp = new byte[((buffer.length - 1) * 2) + 1];
-
- int j = 0;
- for (int i = head; i != tail;) {
- tmp[j] = buffer[i];
- buffer[i] = 0;
-
- j++;
- i++;
- if (i == buffer.length) {
- i = 0;
- }
- }
-
- buffer = tmp;
- head = 0;
- tail = j;
- }
-
- buffer[tail] = b;
- tail++;
- if (tail >= buffer.length) {
- tail = 0;
- }
- return true;
- }
-
- /**
- * Returns the next object in the buffer.
- *
- * @return the next object in the buffer
- * @throws BufferUnderflowException if this buffer is empty
- */
- public byte get() {
- if (isEmpty()) {
- throw new IllegalStateException("The buffer is already empty");
- }
-
- return buffer[head];
- }
-
- /**
- * Removes the next object from the buffer
- *
- * @return the removed object
- * @throws BufferUnderflowException if this buffer is empty
- */
- public byte remove() {
- if (isEmpty()) {
- throw new IllegalStateException("The buffer is already empty");
- }
-
- byte element = buffer[head];
-
- head++;
- if (head >= buffer.length) {
- head = 0;
- }
-
- return element;
- }
-
- /**
- * Increments the internal index.
- *
- * @param index the index to increment
- * @return the updated index
- */
- private int increment(int index) {
- index++;
- if (index >= buffer.length) {
- index = 0;
- }
- return index;
- }
-
- /**
- * Decrements the internal index.
- *
- * @param index the index to decrement
- * @return the updated index
- */
- private int decrement(int index) {
- index--;
- if (index < 0) {
- index = buffer.length - 1;
- }
- return index;
- }
-
- /**
- * Returns an iterator over this buffer's elements.
- *
- * @return an iterator over this buffer's elements
- */
- public Iterator iterator() {
- return new Iterator() {
-
- private int index = head;
- private int lastReturnedIndex = -1;
-
- public boolean hasNext() {
- return index != tail;
-
- }
-
- public Object next() {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- lastReturnedIndex = index;
- index = increment(index);
- return new Byte(buffer[lastReturnedIndex]);
- }
-
- public void remove() {
- if (lastReturnedIndex == -1) {
- throw new IllegalStateException();
- }
-
- // First element can be removed quickly
- if (lastReturnedIndex == head) {
- UnboundedFifoByteBuffer.this.remove();
- lastReturnedIndex = -1;
- return;
- }
-
- // Other elements require us to shift the subsequent elements
- int i = lastReturnedIndex + 1;
- while (i != tail) {
- if (i >= buffer.length) {
- buffer[i - 1] = buffer[0];
- i = 0;
- } else {
- buffer[i - 1] = buffer[i];
- i++;
- }
- }
-
- lastReturnedIndex = -1;
- tail = decrement(tail);
- buffer[tail] = 0;
- index = decrement(index);
- }
-
- };
- }
-
-} \ No newline at end of file
diff --git a/src/org/apache/james/mime4j/field/AddressListField.java b/src/org/apache/james/mime4j/field/AddressListField.java
deleted file mode 100644
index 0e4297c76..000000000
--- a/src/org/apache/james/mime4j/field/AddressListField.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.james.mime4j.field.address.AddressList;
-import org.apache.james.mime4j.field.address.parser.ParseException;
-
-public class AddressListField extends Field {
- private AddressList addressList;
- private ParseException parseException;
-
- protected AddressListField(String name, String body, String raw, AddressList addressList, ParseException parseException) {
- super(name, body, raw);
- this.addressList = addressList;
- this.parseException = parseException;
- }
-
- public AddressList getAddressList() {
- return addressList;
- }
-
- public ParseException getParseException() {
- return parseException;
- }
-
- public static class Parser implements FieldParser {
- private static Log log = LogFactory.getLog(Parser.class);
-
- public Field parse(final String name, final String body, final String raw) {
- AddressList addressList = null;
- ParseException parseException = null;
- try {
- addressList = AddressList.parse(body);
- }
- catch (ParseException e) {
- if (log.isDebugEnabled()) {
- log.debug("Parsing value '" + body + "': "+ e.getMessage());
- }
- parseException = e;
- }
- return new AddressListField(name, body, raw, addressList, parseException);
- }
- }
-}
diff --git a/src/org/apache/james/mime4j/field/ContentTransferEncodingField.java b/src/org/apache/james/mime4j/field/ContentTransferEncodingField.java
deleted file mode 100644
index eb6151377..000000000
--- a/src/org/apache/james/mime4j/field/ContentTransferEncodingField.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field;
-
-
-
-/**
- * Represents a <code>Content-Transfer-Encoding</code> field.
- *
- *
- * @version $Id: ContentTransferEncodingField.java,v 1.2 2004/10/02 12:41:11 ntherning Exp $
- */
-public class ContentTransferEncodingField extends Field {
- /**
- * The <code>7bit</code> encoding.
- */
- public static final String ENC_7BIT = "7bit";
- /**
- * The <code>8bit</code> encoding.
- */
- public static final String ENC_8BIT = "8bit";
- /**
- * The <code>binary</code> encoding.
- */
- public static final String ENC_BINARY = "binary";
- /**
- * The <code>quoted-printable</code> encoding.
- */
- public static final String ENC_QUOTED_PRINTABLE = "quoted-printable";
- /**
- * The <code>base64</code> encoding.
- */
- public static final String ENC_BASE64 = "base64";
-
- private String encoding;
-
- protected ContentTransferEncodingField(String name, String body, String raw, String encoding) {
- super(name, body, raw);
- this.encoding = encoding;
- }
-
- /**
- * Gets the encoding defined in this field.
- *
- * @return the encoding or an empty string if not set.
- */
- public String getEncoding() {
- return encoding;
- }
-
- /**
- * Gets the encoding of the given field if. Returns the default
- * <code>7bit</code> if not set or if
- * <code>f</code> is <code>null</code>.
- *
- * @return the encoding.
- */
- public static String getEncoding(ContentTransferEncodingField f) {
- if (f != null && f.getEncoding().length() != 0) {
- return f.getEncoding();
- }
- return ENC_7BIT;
- }
-
- public static class Parser implements FieldParser {
- public Field parse(final String name, final String body, final String raw) {
- final String encoding = body.trim().toLowerCase();
- return new ContentTransferEncodingField(name, body, raw, encoding);
- }
- }
-}
diff --git a/src/org/apache/james/mime4j/field/ContentTypeField.java b/src/org/apache/james/mime4j/field/ContentTypeField.java
deleted file mode 100644
index 51616419d..000000000
--- a/src/org/apache/james/mime4j/field/ContentTypeField.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field;
-
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.james.mime4j.field.contenttype.parser.ContentTypeParser;
-import org.apache.james.mime4j.field.contenttype.parser.ParseException;
-import org.apache.james.mime4j.field.contenttype.parser.TokenMgrError;
-
-/**
- * Represents a <code>Content-Type</code> field.
- *
- * <p>TODO: Remove dependency on Java 1.4 regexps</p>
- *
- *
- * @version $Id: ContentTypeField.java,v 1.6 2005/01/27 14:16:31 ntherning Exp $
- */
-public class ContentTypeField extends Field {
-
- /**
- * The prefix of all <code>multipart</code> MIME types.
- */
- public static final String TYPE_MULTIPART_PREFIX = "multipart/";
- /**
- * The <code>multipart/digest</code> MIME type.
- */
- public static final String TYPE_MULTIPART_DIGEST = "multipart/digest";
- /**
- * The <code>text/plain</code> MIME type.
- */
- public static final String TYPE_TEXT_PLAIN = "text/plain";
- /**
- * The <code>message/rfc822</code> MIME type.
- */
- public static final String TYPE_MESSAGE_RFC822 = "message/rfc822";
- /**
- * The name of the <code>boundary</code> parameter.
- */
- public static final String PARAM_BOUNDARY = "boundary";
- /**
- * The name of the <code>charset</code> parameter.
- */
- public static final String PARAM_CHARSET = "charset";
-
- private String mimeType = "";
- private Map parameters = null;
- private ParseException parseException;
-
- protected ContentTypeField(String name, String body, String raw, String mimeType, Map parameters, ParseException parseException) {
- super(name, body, raw);
- this.mimeType = mimeType;
- this.parameters = parameters;
- this.parseException = parseException;
- }
-
- /**
- * Gets the exception that was raised during parsing of
- * the field value, if any; otherwise, null.
- */
- public ParseException getParseException() {
- return parseException;
- }
-
- /**
- * Gets the MIME type defined in this Content-Type field.
- *
- * @return the MIME type or an empty string if not set.
- */
- public String getMimeType() {
- return mimeType;
- }
-
- /**
- * Gets the MIME type defined in the child's
- * Content-Type field or derives a MIME type from the parent
- * if child is <code>null</code> or hasn't got a MIME type value set.
- * If child's MIME type is multipart but no boundary
- * has been set the MIME type of child will be derived from
- * the parent.
- *
- * @param child the child.
- * @param parent the parent.
- * @return the MIME type.
- */
- public static String getMimeType(ContentTypeField child,
- ContentTypeField parent) {
-
- if (child == null || child.getMimeType().length() == 0
- || child.isMultipart() && child.getBoundary() == null) {
-
- if (parent != null && parent.isMimeType(TYPE_MULTIPART_DIGEST)) {
- return TYPE_MESSAGE_RFC822;
- } else {
- return TYPE_TEXT_PLAIN;
- }
- }
-
- return child.getMimeType();
- }
-
- /**
- * Gets the value of a parameter. Parameter names are case-insensitive.
- *
- * @param name the name of the parameter to get.
- * @return the parameter value or <code>null</code> if not set.
- */
- public String getParameter(String name) {
- return parameters != null
- ? (String) parameters.get(name.toLowerCase())
- : null;
- }
-
- /**
- * Gets all parameters.
- *
- * @return the parameters.
- */
- public Map getParameters() {
- return parameters != null
- ? Collections.unmodifiableMap(parameters)
- : Collections.EMPTY_MAP;
- }
-
- /**
- * Gets the value of the <code>boundary</code> parameter if set.
- *
- * @return the <code>boundary</code> parameter value or <code>null</code>
- * if not set.
- */
- public String getBoundary() {
- return getParameter(PARAM_BOUNDARY);
- }
-
- /**
- * Gets the value of the <code>charset</code> parameter if set.
- *
- * @return the <code>charset</code> parameter value or <code>null</code>
- * if not set.
- */
- public String getCharset() {
- return getParameter(PARAM_CHARSET);
- }
-
- /**
- * Gets the value of the <code>charset</code> parameter if set for the
- * given field. Returns the default <code>us-ascii</code> if not set or if
- * <code>f</code> is <code>null</code>.
- *
- * @return the <code>charset</code> parameter value.
- */
- public static String getCharset(ContentTypeField f) {
- if (f != null) {
- if (f.getCharset() != null && f.getCharset().length() > 0) {
- return f.getCharset();
- }
- }
- return "us-ascii";
- }
-
- /**
- * Determines if the MIME type of this field matches the given one.
- *
- * @param mimeType the MIME type to match against.
- * @return <code>true</code> if the MIME type of this field matches,
- * <code>false</code> otherwise.
- */
- public boolean isMimeType(String mimeType) {
- return this.mimeType.equalsIgnoreCase(mimeType);
- }
-
- /**
- * Determines if the MIME type of this field is <code>multipart/*</code>.
- *
- * @return <code>true</code> if this field is has a <code>multipart/*</code>
- * MIME type, <code>false</code> otherwise.
- */
- public boolean isMultipart() {
- return mimeType.startsWith(TYPE_MULTIPART_PREFIX);
- }
-
- public static class Parser implements FieldParser {
- private static Log log = LogFactory.getLog(Parser.class);
-
- public Field parse(final String name, final String body, final String raw) {
- ParseException parseException = null;
- String mimeType = "";
- Map parameters = null;
-
- ContentTypeParser parser = new ContentTypeParser(new StringReader(body));
- try {
- parser.parseAll();
- }
- catch (ParseException e) {
- if (log.isDebugEnabled()) {
- log.debug("Parsing value '" + body + "': "+ e.getMessage());
- }
- parseException = e;
- }
- catch (TokenMgrError e) {
- if (log.isDebugEnabled()) {
- log.debug("Parsing value '" + body + "': "+ e.getMessage());
- }
- parseException = new ParseException(e.getMessage());
- }
-
- try {
- final String type = parser.getType();
- final String subType = parser.getSubType();
-
- if (type != null && subType != null) {
- mimeType = (type + "/" + parser.getSubType()).toLowerCase();
-
- ArrayList paramNames = parser.getParamNames();
- ArrayList paramValues = parser.getParamValues();
-
- if (paramNames != null && paramValues != null) {
- for (int i = 0; i < paramNames.size() && i < paramValues.size(); i++) {
- if (parameters == null)
- parameters = new HashMap((int)(paramNames.size() * 1.3 + 1));
- String paramName = ((String)paramNames.get(i)).toLowerCase();
- String paramValue = ((String)paramValues.get(i));
- parameters.put(paramName, paramValue);
- }
- }
- }
- }
- catch (NullPointerException npe) {
- }
- return new ContentTypeField(name, body, raw, mimeType, parameters, parseException);
- }
- }
-}
diff --git a/src/org/apache/james/mime4j/field/DateTimeField.java b/src/org/apache/james/mime4j/field/DateTimeField.java
deleted file mode 100644
index a7b24b5bd..000000000
--- a/src/org/apache/james/mime4j/field/DateTimeField.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.james.mime4j.field.datetime.DateTime;
-import org.apache.james.mime4j.field.datetime.parser.ParseException;
-
-import java.util.Date;
-
-public class DateTimeField extends Field {
- private Date date;
- private ParseException parseException;
-
- protected DateTimeField(String name, String body, String raw, Date date, ParseException parseException) {
- super(name, body, raw);
- this.date = date;
- this.parseException = parseException;
- }
-
- public Date getDate() {
- return date;
- }
-
- public ParseException getParseException() {
- return parseException;
- }
-
- public static class Parser implements FieldParser {
- private static Log log = LogFactory.getLog(Parser.class);
-
- public Field parse(final String name, final String body, final String raw) {
- Date date = null;
- ParseException parseException = null;
- try {
- date = DateTime.parse(body).getDate();
- }
- catch (ParseException e) {
- if (log.isDebugEnabled()) {
- log.debug("Parsing value '" + body + "': "+ e.getMessage());
- }
- parseException = e;
- }
- return new DateTimeField(name, body, raw, date, parseException);
- }
- }
-}
diff --git a/src/org/apache/james/mime4j/field/DefaultFieldParser.java b/src/org/apache/james/mime4j/field/DefaultFieldParser.java
deleted file mode 100644
index 84fcdcb2d..000000000
--- a/src/org/apache/james/mime4j/field/DefaultFieldParser.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2006 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field;
-
-public class DefaultFieldParser extends DelegatingFieldParser {
-
- public DefaultFieldParser() {
- setFieldParser(Field.CONTENT_TRANSFER_ENCODING, new ContentTransferEncodingField.Parser());
- setFieldParser(Field.CONTENT_TYPE, new ContentTypeField.Parser());
-
- final DateTimeField.Parser dateTimeParser = new DateTimeField.Parser();
- setFieldParser(Field.DATE, dateTimeParser);
- setFieldParser(Field.RESENT_DATE, dateTimeParser);
-
- final MailboxListField.Parser mailboxListParser = new MailboxListField.Parser();
- setFieldParser(Field.FROM, mailboxListParser);
- setFieldParser(Field.RESENT_FROM, mailboxListParser);
-
- final MailboxField.Parser mailboxParser = new MailboxField.Parser();
- setFieldParser(Field.SENDER, mailboxParser);
- setFieldParser(Field.RESENT_SENDER, mailboxParser);
-
- final AddressListField.Parser addressListParser = new AddressListField.Parser();
- setFieldParser(Field.TO, addressListParser);
- setFieldParser(Field.RESENT_TO, addressListParser);
- setFieldParser(Field.CC, addressListParser);
- setFieldParser(Field.RESENT_CC, addressListParser);
- setFieldParser(Field.BCC, addressListParser);
- setFieldParser(Field.RESENT_BCC, addressListParser);
- setFieldParser(Field.REPLY_TO, addressListParser);
- }
-}
diff --git a/src/org/apache/james/mime4j/field/DelegatingFieldParser.java b/src/org/apache/james/mime4j/field/DelegatingFieldParser.java
deleted file mode 100644
index e7787a336..000000000
--- a/src/org/apache/james/mime4j/field/DelegatingFieldParser.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2006 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class DelegatingFieldParser implements FieldParser {
-
- private Map parsers = new HashMap();
- private FieldParser defaultParser = new UnstructuredField.Parser();
-
- /**
- * Sets the parser used for the field named <code>name</code>.
- * @param name the name of the field
- * @param parser the parser for fields named <code>name</code>
- */
- public void setFieldParser(final String name, final FieldParser parser) {
- parsers.put(name.toLowerCase(), parser);
- }
-
- public FieldParser getParser(final String name) {
- final FieldParser field = (FieldParser) parsers.get(name.toLowerCase());
- if(field==null) {
- return defaultParser;
- }
- return field;
- }
-
- public Field parse(final String name, final String body, final String raw) {
- final FieldParser parser = getParser(name);
- return parser.parse(name, body, raw);
- }
-}
diff --git a/src/org/apache/james/mime4j/field/Field.java b/src/org/apache/james/mime4j/field/Field.java
deleted file mode 100644
index 7c2a20dc8..000000000
--- a/src/org/apache/james/mime4j/field/Field.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * The base class of all field classes.
- *
- *
- * @version $Id: Field.java,v 1.6 2004/10/25 07:26:46 ntherning Exp $
- */
-public abstract class Field {
- public static final String SENDER = "Sender";
- public static final String FROM = "From";
- public static final String TO = "To";
- public static final String CC = "Cc";
- public static final String BCC = "Bcc";
- public static final String REPLY_TO = "Reply-To";
- public static final String RESENT_SENDER = "Resent-Sender";
- public static final String RESENT_FROM = "Resent-From";
- public static final String RESENT_TO = "Resent-To";
- public static final String RESENT_CC = "Resent-Cc";
- public static final String RESENT_BCC = "Resent-Bcc";
-
- public static final String DATE = "Date";
- public static final String RESENT_DATE = "Resent-Date";
-
- public static final String SUBJECT = "Subject";
- public static final String CONTENT_TYPE = "Content-Type";
- public static final String CONTENT_TRANSFER_ENCODING =
- "Content-Transfer-Encoding";
-
- private static final String FIELD_NAME_PATTERN =
- "^([\\x21-\\x39\\x3b-\\x7e]+)[ \t]*:";
- private static final Pattern fieldNamePattern =
- Pattern.compile(FIELD_NAME_PATTERN);
-
- private static final DefaultFieldParser parser = new DefaultFieldParser();
-
- private final String name;
- private final String body;
- private final String raw;
-
- protected Field(final String name, final String body, final String raw) {
- this.name = name;
- this.body = body;
- this.raw = raw;
- }
-
- /**
- * Parses the given string and returns an instance of the
- * <code>Field</code> class. The type of the class returned depends on
- * the field name:
- * <table>
- * <tr>
- * <td><em>Field name</em></td><td><em>Class returned</em></td>
- * <td>Content-Type</td><td>org.apache.james.mime4j.field.ContentTypeField</td>
- * <td>other</td><td>org.apache.james.mime4j.field.UnstructuredField</td>
- * </tr>
- * </table>
- *
- * @param s the string to parse.
- * @return a <code>Field</code> instance.
- * @throws IllegalArgumentException on parse errors.
- */
- public static Field parse(final String raw) {
-
- /*
- * Unfold the field.
- */
- final String unfolded = raw.replaceAll("\r|\n", "");
-
- /*
- * Split into name and value.
- */
- final Matcher fieldMatcher = fieldNamePattern.matcher(unfolded);
- if (!fieldMatcher.find()) {
- throw new IllegalArgumentException("Invalid field in string");
- }
- final String name = fieldMatcher.group(1);
-
- String body = unfolded.substring(fieldMatcher.end());
- if (body.length() > 0 && body.charAt(0) == ' ') {
- body = body.substring(1);
- }
-
- return parser.parse(name, body, raw);
- }
-
- /**
- * Gets the default parser used to parse fields.
- * @return the default field parser
- */
- public static DefaultFieldParser getParser() {
- return parser;
- }
-
- /**
- * Gets the name of the field (<code>Subject</code>,
- * <code>From</code>, etc).
- *
- * @return the field name.
- */
- public String getName() {
- return name;
- }
-
- /**
- * Gets the original raw field string.
- *
- * @return the original raw field string.
- */
- public String getRaw() {
- return raw;
- }
-
- /**
- * Gets the unfolded, unparsed and possibly encoded (see RFC 2047) field
- * body string.
- *
- * @return the unfolded unparsed field body string.
- */
- public String getBody() {
- return body;
- }
-
- /**
- * Determines if this is a <code>Content-Type</code> field.
- *
- * @return <code>true</code> if this is a <code>Content-Type</code> field,
- * <code>false</code> otherwise.
- */
- public boolean isContentType() {
- return CONTENT_TYPE.equalsIgnoreCase(name);
- }
-
- /**
- * Determines if this is a <code>Subject</code> field.
- *
- * @return <code>true</code> if this is a <code>Subject</code> field,
- * <code>false</code> otherwise.
- */
- public boolean isSubject() {
- return SUBJECT.equalsIgnoreCase(name);
- }
-
- /**
- * Determines if this is a <code>From</code> field.
- *
- * @return <code>true</code> if this is a <code>From</code> field,
- * <code>false</code> otherwise.
- */
- public boolean isFrom() {
- return FROM.equalsIgnoreCase(name);
- }
-
- /**
- * Determines if this is a <code>To</code> field.
- *
- * @return <code>true</code> if this is a <code>To</code> field,
- * <code>false</code> otherwise.
- */
- public boolean isTo() {
- return TO.equalsIgnoreCase(name);
- }
-
- /**
- * @see #getRaw()
- */
- public String toString() {
- return raw;
- }
-}
diff --git a/src/org/apache/james/mime4j/field/FieldParser.java b/src/org/apache/james/mime4j/field/FieldParser.java
deleted file mode 100644
index 4f33c9e26..000000000
--- a/src/org/apache/james/mime4j/field/FieldParser.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2006 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field;
-
-public interface FieldParser {
-
- Field parse(final String name, final String body, final String raw);
-}
diff --git a/src/org/apache/james/mime4j/field/MailboxField.java b/src/org/apache/james/mime4j/field/MailboxField.java
deleted file mode 100644
index 96cca551f..000000000
--- a/src/org/apache/james/mime4j/field/MailboxField.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.james.mime4j.field.address.AddressList;
-import org.apache.james.mime4j.field.address.Mailbox;
-import org.apache.james.mime4j.field.address.MailboxList;
-import org.apache.james.mime4j.field.address.parser.ParseException;
-
-public class MailboxField extends Field {
- private final Mailbox mailbox;
- private final ParseException parseException;
-
- protected MailboxField(final String name, final String body, final String raw, final Mailbox mailbox, final ParseException parseException) {
- super(name, body, raw);
- this.mailbox = mailbox;
- this.parseException = parseException;
- }
-
- public Mailbox getMailbox() {
- return mailbox;
- }
-
- public ParseException getParseException() {
- return parseException;
- }
-
- public static class Parser implements FieldParser {
- private static Log log = LogFactory.getLog(Parser.class);
-
- public Field parse(final String name, final String body, final String raw) {
- Mailbox mailbox = null;
- ParseException parseException = null;
- try {
- MailboxList mailboxList = AddressList.parse(body).flatten();
- if (mailboxList.size() > 0) {
- mailbox = mailboxList.get(0);
- }
- }
- catch (ParseException e) {
- if (log.isDebugEnabled()) {
- log.debug("Parsing value '" + body + "': "+ e.getMessage());
- }
- parseException = e;
- }
- return new MailboxField(name, body, raw, mailbox, parseException);
- }
- }
-}
diff --git a/src/org/apache/james/mime4j/field/MailboxListField.java b/src/org/apache/james/mime4j/field/MailboxListField.java
deleted file mode 100644
index efb18cd35..000000000
--- a/src/org/apache/james/mime4j/field/MailboxListField.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.james.mime4j.field.address.AddressList;
-import org.apache.james.mime4j.field.address.MailboxList;
-import org.apache.james.mime4j.field.address.parser.ParseException;
-
-public class MailboxListField extends Field {
-
- private MailboxList mailboxList;
- private ParseException parseException;
-
- protected MailboxListField(final String name, final String body, final String raw, final MailboxList mailboxList, final ParseException parseException) {
- super(name, body, raw);
- this.mailboxList = mailboxList;
- this.parseException = parseException;
- }
-
- public MailboxList getMailboxList() {
- return mailboxList;
- }
-
- public ParseException getParseException() {
- return parseException;
- }
-
- public static class Parser implements FieldParser {
- private static Log log = LogFactory.getLog(Parser.class);
-
- public Field parse(final String name, final String body, final String raw) {
- MailboxList mailboxList = null;
- ParseException parseException = null;
- try {
- mailboxList = AddressList.parse(body).flatten();
- }
- catch (ParseException e) {
- if (log.isDebugEnabled()) {
- log.debug("Parsing value '" + body + "': "+ e.getMessage());
- }
- parseException = e;
- }
- return new MailboxListField(name, body, raw, mailboxList, parseException);
- }
- }
-}
diff --git a/src/org/apache/james/mime4j/field/UnstructuredField.java b/src/org/apache/james/mime4j/field/UnstructuredField.java
deleted file mode 100644
index 5e2adf9f2..000000000
--- a/src/org/apache/james/mime4j/field/UnstructuredField.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field;
-
-import org.apache.james.mime4j.decoder.DecoderUtil;
-
-
-/**
- * Simple unstructured field such as <code>Subject</code>.
- *
- *
- * @version $Id: UnstructuredField.java,v 1.3 2004/10/25 07:26:46 ntherning Exp $
- */
-public class UnstructuredField extends Field {
- private String value;
-
- protected UnstructuredField(String name, String body, String raw, String value) {
- super(name, body, raw);
- this.value = value;
- }
-
- public String getValue() {
- return value;
- }
-
- public static class Parser implements FieldParser {
- public Field parse(final String name, final String body, final String raw) {
- final String value = DecoderUtil.decodeEncodedWords(body);
- return new UnstructuredField(name, body, raw, value);
- }
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/Address.java b/src/org/apache/james/mime4j/field/address/Address.java
deleted file mode 100644
index 47cee0ba0..000000000
--- a/src/org/apache/james/mime4j/field/address/Address.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field.address;
-
-import java.util.ArrayList;
-
-/**
- * The abstract base for classes that represent RFC2822 addresses.
- * This includes groups and mailboxes.
- *
- * Currently, no public methods are introduced on this class.
- *
- *
- */
-public abstract class Address {
-
- /**
- * Adds any mailboxes represented by this address
- * into the given ArrayList. Note that this method
- * has default (package) access, so a doAddMailboxesTo
- * method is needed to allow the behavior to be
- * overridden by subclasses.
- */
- final void addMailboxesTo(ArrayList results) {
- doAddMailboxesTo(results);
- }
-
- /**
- * Adds any mailboxes represented by this address
- * into the given ArrayList. Must be overridden by
- * concrete subclasses.
- */
- protected abstract void doAddMailboxesTo(ArrayList results);
-
-}
diff --git a/src/org/apache/james/mime4j/field/address/AddressList.java b/src/org/apache/james/mime4j/field/address/AddressList.java
deleted file mode 100644
index 75072bde4..000000000
--- a/src/org/apache/james/mime4j/field/address/AddressList.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field.address;
-
-import org.apache.james.mime4j.field.address.parser.AddressListParser;
-import org.apache.james.mime4j.field.address.parser.ParseException;
-
-import java.io.StringReader;
-import java.util.ArrayList;
-
-/**
- * An immutable, random-access list of Address objects.
- *
- *
- */
-public class AddressList {
-
- private ArrayList addresses;
-
- /**
- * @param addresses An ArrayList that contains only Address objects.
- * @param dontCopy true iff it is not possible for the addresses ArrayList to be modified by someone else.
- */
- public AddressList(ArrayList addresses, boolean dontCopy) {
- if (addresses != null)
- this.addresses = (dontCopy ? addresses : (ArrayList) addresses.clone());
- else
- this.addresses = new ArrayList(0);
- }
-
- /**
- * The number of elements in this list.
- */
- public int size() {
- return addresses.size();
- }
-
- /**
- * Gets an address.
- */
- public Address get(int index) {
- if (0 > index || size() <= index)
- throw new IndexOutOfBoundsException();
- return (Address) addresses.get(index);
- }
-
- /**
- * Returns a flat list of all mailboxes represented
- * in this address list. Use this if you don't care
- * about grouping.
- */
- public MailboxList flatten() {
- // in the common case, all addresses are mailboxes
- boolean groupDetected = false;
- for (int i = 0; i < size(); i++) {
- if (!(get(i) instanceof Mailbox)) {
- groupDetected = true;
- break;
- }
- }
-
- if (!groupDetected)
- return new MailboxList(addresses, true);
-
- ArrayList results = new ArrayList();
- for (int i = 0; i < size(); i++) {
- Address addr = get(i);
- addr.addMailboxesTo(results);
- }
-
- // copy-on-construct this time, because subclasses
- // could have held onto a reference to the results
- return new MailboxList(results, false);
- }
-
- /**
- * Dumps a representation of this address list to
- * stdout, for debugging purposes.
- */
- public void print() {
- for (int i = 0; i < size(); i++) {
- Address addr = get(i);
- System.out.println(addr.toString());
- }
- }
-
-
-
- /**
- * Parse the address list string, such as the value
- * of a From, To, Cc, Bcc, Sender, or Reply-To
- * header.
- *
- * The string MUST be unfolded already.
- */
- public static AddressList parse(String rawAddressList) throws ParseException {
- AddressListParser parser = new AddressListParser(new StringReader(rawAddressList));
- return Builder.getInstance().buildAddressList(parser.parse());
- }
-
- /**
- * Test console.
- */
- public static void main(String[] args) throws Exception {
- java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
- while (true) {
- try {
- System.out.print("> ");
- String line = reader.readLine();
- if (line.length() == 0 || line.toLowerCase().equals("exit") || line.toLowerCase().equals("quit")) {
- System.out.println("Goodbye.");
- return;
- }
- AddressList list = parse(line);
- list.print();
- }
- catch(Exception e) {
- e.printStackTrace();
- Thread.sleep(300);
- }
- }
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/Builder.java b/src/org/apache/james/mime4j/field/address/Builder.java
deleted file mode 100644
index 3699afed7..000000000
--- a/src/org/apache/james/mime4j/field/address/Builder.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field.address;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-
-import org.apache.james.mime4j.decoder.DecoderUtil;
-import org.apache.james.mime4j.field.address.parser.*;
-import org.apache.james.mime4j.field.address.parser.ASTaddr_spec;
-import org.apache.james.mime4j.field.address.parser.ASTaddress;
-import org.apache.james.mime4j.field.address.parser.ASTaddress_list;
-import org.apache.james.mime4j.field.address.parser.ASTangle_addr;
-import org.apache.james.mime4j.field.address.parser.ASTdomain;
-import org.apache.james.mime4j.field.address.parser.ASTgroup_body;
-import org.apache.james.mime4j.field.address.parser.ASTlocal_part;
-import org.apache.james.mime4j.field.address.parser.ASTmailbox;
-import org.apache.james.mime4j.field.address.parser.ASTname_addr;
-import org.apache.james.mime4j.field.address.parser.ASTphrase;
-import org.apache.james.mime4j.field.address.parser.ASTroute;
-import org.apache.james.mime4j.field.address.parser.Node;
-import org.apache.james.mime4j.field.address.parser.SimpleNode;
-import org.apache.james.mime4j.field.address.parser.Token;
-
-/**
- * Transforms the JJTree-generated abstract syntax tree
- * into a graph of org.apache.james.mime4j.field.address objects.
- *
- *
- */
-class Builder {
-
- private static Builder singleton = new Builder();
-
- public static Builder getInstance() {
- return singleton;
- }
-
-
-
- public AddressList buildAddressList(ASTaddress_list node) {
- ArrayList list = new ArrayList();
- for (int i = 0; i < node.jjtGetNumChildren(); i++) {
- ASTaddress childNode = (ASTaddress) node.jjtGetChild(i);
- Address address = buildAddress(childNode);
- list.add(address);
- }
- return new AddressList(list, true);
- }
-
- private Address buildAddress(ASTaddress node) {
- ChildNodeIterator it = new ChildNodeIterator(node);
- Node n = it.nextNode();
- if (n instanceof ASTaddr_spec) {
- return buildAddrSpec((ASTaddr_spec)n);
- }
- else if (n instanceof ASTangle_addr) {
- return buildAngleAddr((ASTangle_addr)n);
- }
- else if (n instanceof ASTphrase) {
- String name = buildString((ASTphrase)n, false);
- Node n2 = it.nextNode();
- if (n2 instanceof ASTgroup_body) {
- return new Group(name, buildGroupBody((ASTgroup_body)n2));
- }
- else if (n2 instanceof ASTangle_addr) {
- name = DecoderUtil.decodeEncodedWords(name);
- return new NamedMailbox(name, buildAngleAddr((ASTangle_addr)n2));
- }
- else {
- throw new IllegalStateException();
- }
- }
- else {
- throw new IllegalStateException();
- }
- }
-
-
-
- private MailboxList buildGroupBody(ASTgroup_body node) {
- ArrayList results = new ArrayList();
- ChildNodeIterator it = new ChildNodeIterator(node);
- while (it.hasNext()) {
- Node n = it.nextNode();
- if (n instanceof ASTmailbox)
- results.add(buildMailbox((ASTmailbox)n));
- else
- throw new IllegalStateException();
- }
- return new MailboxList(results, true);
- }
-
- private Mailbox buildMailbox(ASTmailbox node) {
- ChildNodeIterator it = new ChildNodeIterator(node);
- Node n = it.nextNode();
- if (n instanceof ASTaddr_spec) {
- return buildAddrSpec((ASTaddr_spec)n);
- }
- else if (n instanceof ASTangle_addr) {
- return buildAngleAddr((ASTangle_addr)n);
- }
- else if (n instanceof ASTname_addr) {
- return buildNameAddr((ASTname_addr)n);
- }
- else {
- throw new IllegalStateException();
- }
- }
-
- private NamedMailbox buildNameAddr(ASTname_addr node) {
- ChildNodeIterator it = new ChildNodeIterator(node);
- Node n = it.nextNode();
- String name;
- if (n instanceof ASTphrase) {
- name = buildString((ASTphrase)n, false);
- }
- else {
- throw new IllegalStateException();
- }
-
- n = it.nextNode();
- if (n instanceof ASTangle_addr) {
- name = DecoderUtil.decodeEncodedWords(name);
- return new NamedMailbox(name, buildAngleAddr((ASTangle_addr) n));
- }
- else {
- throw new IllegalStateException();
- }
- }
-
- private Mailbox buildAngleAddr(ASTangle_addr node) {
- ChildNodeIterator it = new ChildNodeIterator(node);
- DomainList route = null;
- Node n = it.nextNode();
- if (n instanceof ASTroute) {
- route = buildRoute((ASTroute)n);
- n = it.nextNode();
- }
- else if (n instanceof ASTaddr_spec)
- ; // do nothing
- else
- throw new IllegalStateException();
-
- if (n instanceof ASTaddr_spec)
- return buildAddrSpec(route, (ASTaddr_spec)n);
- else
- throw new IllegalStateException();
- }
-
- private DomainList buildRoute(ASTroute node) {
- ArrayList results = new ArrayList(node.jjtGetNumChildren());
- ChildNodeIterator it = new ChildNodeIterator(node);
- while (it.hasNext()) {
- Node n = it.nextNode();
- if (n instanceof ASTdomain)
- results.add(buildString((ASTdomain)n, true));
- else
- throw new IllegalStateException();
- }
- return new DomainList(results, true);
- }
-
- private Mailbox buildAddrSpec(ASTaddr_spec node) {
- return buildAddrSpec(null, node);
- }
- private Mailbox buildAddrSpec(DomainList route, ASTaddr_spec node) {
- ChildNodeIterator it = new ChildNodeIterator(node);
- String localPart = buildString((ASTlocal_part)it.nextNode(), true);
- String domain = buildString((ASTdomain)it.nextNode(), true);
- return new Mailbox(route, localPart, domain);
- }
-
-
- private String buildString(SimpleNode node, boolean stripSpaces) {
- Token head = node.firstToken;
- Token tail = node.lastToken;
- StringBuffer out = new StringBuffer();
-
- while (head != tail) {
- out.append(head.image);
- head = head.next;
- if (!stripSpaces)
- addSpecials(out, head.specialToken);
- }
- out.append(tail.image);
-
- return out.toString();
- }
-
- private void addSpecials(StringBuffer out, Token specialToken) {
- if (specialToken != null) {
- addSpecials(out, specialToken.specialToken);
- out.append(specialToken.image);
- }
- }
-
- private static class ChildNodeIterator implements Iterator {
-
- private SimpleNode simpleNode;
- private int index;
- private int len;
-
- public ChildNodeIterator(SimpleNode simpleNode) {
- this.simpleNode = simpleNode;
- this.len = simpleNode.jjtGetNumChildren();
- this.index = 0;
- }
-
- public void remove() {
- throw new UnsupportedOperationException();
- }
-
- public boolean hasNext() {
- return index < len;
- }
-
- public Object next() {
- return nextNode();
- }
-
- public Node nextNode() {
- return simpleNode.jjtGetChild(index++);
- }
-
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/DomainList.java b/src/org/apache/james/mime4j/field/address/DomainList.java
deleted file mode 100644
index 23c377e9e..000000000
--- a/src/org/apache/james/mime4j/field/address/DomainList.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field.address;
-
-import java.util.ArrayList;
-
-/**
- * An immutable, random-access list of Strings (that
- * are supposedly domain names or domain literals).
- *
- *
- */
-public class DomainList {
- private ArrayList domains;
-
- /**
- * @param domains An ArrayList that contains only String objects.
- * @param dontCopy true iff it is not possible for the domains ArrayList to be modified by someone else.
- */
- public DomainList(ArrayList domains, boolean dontCopy) {
- if (domains != null)
- this.domains = (dontCopy ? domains : (ArrayList) domains.clone());
- else
- this.domains = new ArrayList(0);
- }
-
- /**
- * The number of elements in this list.
- */
- public int size() {
- return domains.size();
- }
-
- /**
- * Gets the domain name or domain literal at the
- * specified index.
- * @throws IndexOutOfBoundsException If index is &lt; 0 or &gt;= size().
- */
- public String get(int index) {
- if (0 > index || size() <= index)
- throw new IndexOutOfBoundsException();
- return (String) domains.get(index);
- }
-
- /**
- * Returns the list of domains formatted as a route
- * string (not including the trailing ':').
- */
- public String toRouteString() {
- StringBuffer out = new StringBuffer();
- for (int i = 0; i < domains.size(); i++) {
- out.append("@");
- out.append(get(i));
- if (i + 1 < domains.size())
- out.append(",");
- }
- return out.toString();
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/Group.java b/src/org/apache/james/mime4j/field/address/Group.java
deleted file mode 100644
index eb4002708..000000000
--- a/src/org/apache/james/mime4j/field/address/Group.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field.address;
-
-import java.util.ArrayList;
-
-/**
- * A named group of zero or more mailboxes.
- *
- *
- */
-public class Group extends Address {
- private String name;
- private MailboxList mailboxList;
-
- /**
- * @param name The group name.
- * @param mailboxes The mailboxes in this group.
- */
- public Group(String name, MailboxList mailboxes) {
- this.name = name;
- this.mailboxList = mailboxes;
- }
-
- /**
- * Returns the group name.
- */
- public String getName() {
- return name;
- }
-
- /**
- * Returns the mailboxes in this group.
- */
- public MailboxList getMailboxes() {
- return mailboxList;
- }
-
- public String toString() {
- StringBuffer buf = new StringBuffer();
- buf.append(name);
- buf.append(":");
- for (int i = 0; i < mailboxList.size(); i++) {
- buf.append(mailboxList.get(i).toString());
- if (i + 1 < mailboxList.size())
- buf.append(",");
- }
- buf.append(";");
- return buf.toString();
- }
-
- protected void doAddMailboxesTo(ArrayList results) {
- for (int i = 0; i < mailboxList.size(); i++)
- results.add(mailboxList.get(i));
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/Mailbox.java b/src/org/apache/james/mime4j/field/address/Mailbox.java
deleted file mode 100644
index 57668abfe..000000000
--- a/src/org/apache/james/mime4j/field/address/Mailbox.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field.address;
-
-import java.util.ArrayList;
-
-/**
- * Represents a single e-mail address.
- *
- *
- */
-public class Mailbox extends Address {
- private DomainList route;
- private String localPart;
- private String domain;
-
- /**
- * Creates a mailbox without a route. Routes are obsolete.
- * @param localPart The part of the e-mail address to the left of the "@".
- * @param domain The part of the e-mail address to the right of the "@".
- */
- public Mailbox(String localPart, String domain) {
- this(null, localPart, domain);
- }
-
- /**
- * Creates a mailbox with a route. Routes are obsolete.
- * @param route The zero or more domains that make up the route. Can be null.
- * @param localPart The part of the e-mail address to the left of the "@".
- * @param domain The part of the e-mail address to the right of the "@".
- */
- public Mailbox(DomainList route, String localPart, String domain) {
- this.route = route;
- this.localPart = localPart;
- this.domain = domain;
- }
-
- /**
- * Returns the route list.
- */
- public DomainList getRoute() {
- return route;
- }
-
- /**
- * Returns the left part of the e-mail address
- * (before "@").
- */
- public String getLocalPart() {
- return localPart;
- }
-
- /**
- * Returns the right part of the e-mail address
- * (after "@").
- */
- public String getDomain() {
- return domain;
- }
-
- /**
- * Formats the address as a string, not including
- * the route.
- *
- * @see #getAddressString(boolean)
- */
- public String getAddressString() {
- return getAddressString(false);
- }
-
- /**
- * Note that this value may not be usable
- * for transport purposes, only display purposes.
- *
- * For example, if the unparsed address was
- *
- * <"Joe Cheng"@joecheng.com>
- *
- * this method would return
- *
- * <Joe Cheng@joecheng.com>
- *
- * which is not valid for transport; the local part
- * would need to be re-quoted.
- *
- * @param includeRoute true if the route should be included if it exists.
- */
- public String getAddressString(boolean includeRoute) {
- return "<" + (!includeRoute || route == null ? "" : route.toRouteString() + ":")
- + localPart
- + (domain == null ? "" : "@")
- + domain + ">";
- }
-
- protected final void doAddMailboxesTo(ArrayList results) {
- results.add(this);
- }
-
- public String toString() {
- return getAddressString();
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/MailboxList.java b/src/org/apache/james/mime4j/field/address/MailboxList.java
deleted file mode 100644
index b25264da3..000000000
--- a/src/org/apache/james/mime4j/field/address/MailboxList.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field.address;
-
-import java.util.ArrayList;
-
-/**
- * An immutable, random-access list of Mailbox objects.
- *
- *
- */
-public class MailboxList {
-
- private ArrayList mailboxes;
-
- /**
- * @param mailboxes An ArrayList that contains only Mailbox objects.
- * @param dontCopy true iff it is not possible for the mailboxes ArrayList to be modified by someone else.
- */
- public MailboxList(ArrayList mailboxes, boolean dontCopy) {
- if (mailboxes != null)
- this.mailboxes = (dontCopy ? mailboxes : (ArrayList) mailboxes.clone());
- else
- this.mailboxes = new ArrayList(0);
- }
-
- /**
- * The number of elements in this list.
- */
- public int size() {
- return mailboxes.size();
- }
-
- /**
- * Gets an address.
- */
- public Mailbox get(int index) {
- if (0 > index || size() <= index)
- throw new IndexOutOfBoundsException();
- return (Mailbox) mailboxes.get(index);
- }
-
- /**
- * Dumps a representation of this mailbox list to
- * stdout, for debugging purposes.
- */
- public void print() {
- for (int i = 0; i < size(); i++) {
- Mailbox mailbox = get(i);
- System.out.println(mailbox.toString());
- }
- }
-
-}
diff --git a/src/org/apache/james/mime4j/field/address/NamedMailbox.java b/src/org/apache/james/mime4j/field/address/NamedMailbox.java
deleted file mode 100644
index dea0d821c..000000000
--- a/src/org/apache/james/mime4j/field/address/NamedMailbox.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field.address;
-
-/**
- * A Mailbox that has a name/description.
- *
- *
- */
-public class NamedMailbox extends Mailbox {
- private String name;
-
- /**
- * @see Mailbox#Mailbox(String, String)
- */
- public NamedMailbox(String name, String localPart, String domain) {
- super(localPart, domain);
- this.name = name;
- }
-
- /**
- * @see Mailbox#Mailbox(DomainList, String, String)
- */
- public NamedMailbox(String name, DomainList route, String localPart, String domain) {
- super(route, localPart, domain);
- this.name = name;
- }
-
- /**
- * Creates a named mailbox based on an unnamed mailbox.
- */
- public NamedMailbox(String name, Mailbox baseMailbox) {
- super(baseMailbox.getRoute(), baseMailbox.getLocalPart(), baseMailbox.getDomain());
- this.name = name;
- }
-
- /**
- * Returns the name of the mailbox.
- */
- public String getName() {
- return this.name;
- }
-
- /**
- * Same features (or problems) as Mailbox.getAddressString(boolean),
- * only more so.
- *
- * @see Mailbox#getAddressString(boolean)
- */
- public String getAddressString(boolean includeRoute) {
- return (name == null ? "" : name + " ") + super.getAddressString(includeRoute);
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/ASTaddr_spec.java b/src/org/apache/james/mime4j/field/address/parser/ASTaddr_spec.java
deleted file mode 100644
index 4d56d000b..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/ASTaddr_spec.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Generated By:JJTree: Do not edit this line. ASTaddr_spec.java */
-
-package org.apache.james.mime4j.field.address.parser;
-
-public class ASTaddr_spec extends SimpleNode {
- public ASTaddr_spec(int id) {
- super(id);
- }
-
- public ASTaddr_spec(AddressListParser p, int id) {
- super(p, id);
- }
-
-
- /** Accept the visitor. **/
- public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
- return visitor.visit(this, data);
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/ASTaddress.java b/src/org/apache/james/mime4j/field/address/parser/ASTaddress.java
deleted file mode 100644
index 47bdeda8e..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/ASTaddress.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Generated By:JJTree: Do not edit this line. ASTaddress.java */
-
-package org.apache.james.mime4j.field.address.parser;
-
-public class ASTaddress extends SimpleNode {
- public ASTaddress(int id) {
- super(id);
- }
-
- public ASTaddress(AddressListParser p, int id) {
- super(p, id);
- }
-
-
- /** Accept the visitor. **/
- public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
- return visitor.visit(this, data);
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/ASTaddress_list.java b/src/org/apache/james/mime4j/field/address/parser/ASTaddress_list.java
deleted file mode 100644
index 737840e38..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/ASTaddress_list.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Generated By:JJTree: Do not edit this line. ASTaddress_list.java */
-
-package org.apache.james.mime4j.field.address.parser;
-
-public class ASTaddress_list extends SimpleNode {
- public ASTaddress_list(int id) {
- super(id);
- }
-
- public ASTaddress_list(AddressListParser p, int id) {
- super(p, id);
- }
-
-
- /** Accept the visitor. **/
- public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
- return visitor.visit(this, data);
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/ASTangle_addr.java b/src/org/apache/james/mime4j/field/address/parser/ASTangle_addr.java
deleted file mode 100644
index 8cb8f421f..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/ASTangle_addr.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Generated By:JJTree: Do not edit this line. ASTangle_addr.java */
-
-package org.apache.james.mime4j.field.address.parser;
-
-public class ASTangle_addr extends SimpleNode {
- public ASTangle_addr(int id) {
- super(id);
- }
-
- public ASTangle_addr(AddressListParser p, int id) {
- super(p, id);
- }
-
-
- /** Accept the visitor. **/
- public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
- return visitor.visit(this, data);
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/ASTdomain.java b/src/org/apache/james/mime4j/field/address/parser/ASTdomain.java
deleted file mode 100644
index b52664386..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/ASTdomain.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Generated By:JJTree: Do not edit this line. ASTdomain.java */
-
-package org.apache.james.mime4j.field.address.parser;
-
-public class ASTdomain extends SimpleNode {
- public ASTdomain(int id) {
- super(id);
- }
-
- public ASTdomain(AddressListParser p, int id) {
- super(p, id);
- }
-
-
- /** Accept the visitor. **/
- public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
- return visitor.visit(this, data);
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/ASTgroup_body.java b/src/org/apache/james/mime4j/field/address/parser/ASTgroup_body.java
deleted file mode 100644
index f6017b9fc..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/ASTgroup_body.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Generated By:JJTree: Do not edit this line. ASTgroup_body.java */
-
-package org.apache.james.mime4j.field.address.parser;
-
-public class ASTgroup_body extends SimpleNode {
- public ASTgroup_body(int id) {
- super(id);
- }
-
- public ASTgroup_body(AddressListParser p, int id) {
- super(p, id);
- }
-
-
- /** Accept the visitor. **/
- public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
- return visitor.visit(this, data);
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/ASTlocal_part.java b/src/org/apache/james/mime4j/field/address/parser/ASTlocal_part.java
deleted file mode 100644
index 5c244fa3e..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/ASTlocal_part.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Generated By:JJTree: Do not edit this line. ASTlocal_part.java */
-
-package org.apache.james.mime4j.field.address.parser;
-
-public class ASTlocal_part extends SimpleNode {
- public ASTlocal_part(int id) {
- super(id);
- }
-
- public ASTlocal_part(AddressListParser p, int id) {
- super(p, id);
- }
-
-
- /** Accept the visitor. **/
- public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
- return visitor.visit(this, data);
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/ASTmailbox.java b/src/org/apache/james/mime4j/field/address/parser/ASTmailbox.java
deleted file mode 100644
index aeb469da1..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/ASTmailbox.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Generated By:JJTree: Do not edit this line. ASTmailbox.java */
-
-package org.apache.james.mime4j.field.address.parser;
-
-public class ASTmailbox extends SimpleNode {
- public ASTmailbox(int id) {
- super(id);
- }
-
- public ASTmailbox(AddressListParser p, int id) {
- super(p, id);
- }
-
-
- /** Accept the visitor. **/
- public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
- return visitor.visit(this, data);
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/ASTname_addr.java b/src/org/apache/james/mime4j/field/address/parser/ASTname_addr.java
deleted file mode 100644
index 846c73167..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/ASTname_addr.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Generated By:JJTree: Do not edit this line. ASTname_addr.java */
-
-package org.apache.james.mime4j.field.address.parser;
-
-public class ASTname_addr extends SimpleNode {
- public ASTname_addr(int id) {
- super(id);
- }
-
- public ASTname_addr(AddressListParser p, int id) {
- super(p, id);
- }
-
-
- /** Accept the visitor. **/
- public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
- return visitor.visit(this, data);
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/ASTphrase.java b/src/org/apache/james/mime4j/field/address/parser/ASTphrase.java
deleted file mode 100644
index 7d711c529..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/ASTphrase.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Generated By:JJTree: Do not edit this line. ASTphrase.java */
-
-package org.apache.james.mime4j.field.address.parser;
-
-public class ASTphrase extends SimpleNode {
- public ASTphrase(int id) {
- super(id);
- }
-
- public ASTphrase(AddressListParser p, int id) {
- super(p, id);
- }
-
-
- /** Accept the visitor. **/
- public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
- return visitor.visit(this, data);
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/ASTroute.java b/src/org/apache/james/mime4j/field/address/parser/ASTroute.java
deleted file mode 100644
index 54ea11523..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/ASTroute.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Generated By:JJTree: Do not edit this line. ASTroute.java */
-
-package org.apache.james.mime4j.field.address.parser;
-
-public class ASTroute extends SimpleNode {
- public ASTroute(int id) {
- super(id);
- }
-
- public ASTroute(AddressListParser p, int id) {
- super(p, id);
- }
-
-
- /** Accept the visitor. **/
- public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
- return visitor.visit(this, data);
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/AddressListParser.java b/src/org/apache/james/mime4j/field/address/parser/AddressListParser.java
deleted file mode 100644
index 6cf08ac1d..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/AddressListParser.java
+++ /dev/null
@@ -1,977 +0,0 @@
-/* Generated By:JJTree&JavaCC: Do not edit this line. AddressListParser.java */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.address.parser;
-
-public class AddressListParser/*@bgen(jjtree)*/implements AddressListParserTreeConstants, AddressListParserConstants {/*@bgen(jjtree)*/
- protected JJTAddressListParserState jjtree = new JJTAddressListParserState();public static void main(String args[]) throws ParseException {
- while (true) {
- try {
- AddressListParser parser = new AddressListParser(System.in);
- parser.parseLine();
- ((SimpleNode)parser.jjtree.rootNode()).dump("> ");
- } catch (Exception x) {
- x.printStackTrace();
- return;
- }
- }
- }
-
- private static void log(String msg) {
- System.out.print(msg);
- }
-
- public ASTaddress_list parse() throws ParseException {
- try {
- parseAll();
- return (ASTaddress_list)jjtree.rootNode();
- } catch (TokenMgrError tme) {
- throw new ParseException(tme.getMessage());
- }
- }
-
-
- void jjtreeOpenNodeScope(Node n) {
- ((SimpleNode)n).firstToken = getToken(1);
- }
-
- void jjtreeCloseNodeScope(Node n) {
- ((SimpleNode)n).lastToken = getToken(0);
- }
-
- final public void parseLine() throws ParseException {
- address_list();
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 1:
- jj_consume_token(1);
- break;
- default:
- jj_la1[0] = jj_gen;
- ;
- }
- jj_consume_token(2);
- }
-
- final public void parseAll() throws ParseException {
- address_list();
- jj_consume_token(0);
- }
-
- final public void address_list() throws ParseException {
- /*@bgen(jjtree) address_list */
- ASTaddress_list jjtn000 = new ASTaddress_list(JJTADDRESS_LIST);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
- try {
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 6:
- case DOTATOM:
- case QUOTEDSTRING:
- address();
- break;
- default:
- jj_la1[1] = jj_gen;
- ;
- }
- label_1:
- while (true) {
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 3:
- ;
- break;
- default:
- jj_la1[2] = jj_gen;
- break label_1;
- }
- jj_consume_token(3);
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 6:
- case DOTATOM:
- case QUOTEDSTRING:
- address();
- break;
- default:
- jj_la1[3] = jj_gen;
- ;
- }
- }
- } catch (Throwable jjte000) {
- if (jjtc000) {
- jjtree.clearNodeScope(jjtn000);
- jjtc000 = false;
- } else {
- jjtree.popNode();
- }
- if (jjte000 instanceof RuntimeException) {
- {if (true) throw (RuntimeException)jjte000;}
- }
- if (jjte000 instanceof ParseException) {
- {if (true) throw (ParseException)jjte000;}
- }
- {if (true) throw (Error)jjte000;}
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
- }
-
- final public void address() throws ParseException {
- /*@bgen(jjtree) address */
- ASTaddress jjtn000 = new ASTaddress(JJTADDRESS);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
- try {
- if (jj_2_1(2147483647)) {
- addr_spec();
- } else {
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 6:
- angle_addr();
- break;
- case DOTATOM:
- case QUOTEDSTRING:
- phrase();
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 4:
- group_body();
- break;
- case 6:
- angle_addr();
- break;
- default:
- jj_la1[4] = jj_gen;
- jj_consume_token(-1);
- throw new ParseException();
- }
- break;
- default:
- jj_la1[5] = jj_gen;
- jj_consume_token(-1);
- throw new ParseException();
- }
- }
- } catch (Throwable jjte000) {
- if (jjtc000) {
- jjtree.clearNodeScope(jjtn000);
- jjtc000 = false;
- } else {
- jjtree.popNode();
- }
- if (jjte000 instanceof RuntimeException) {
- {if (true) throw (RuntimeException)jjte000;}
- }
- if (jjte000 instanceof ParseException) {
- {if (true) throw (ParseException)jjte000;}
- }
- {if (true) throw (Error)jjte000;}
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
- }
-
- final public void mailbox() throws ParseException {
- /*@bgen(jjtree) mailbox */
- ASTmailbox jjtn000 = new ASTmailbox(JJTMAILBOX);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
- try {
- if (jj_2_2(2147483647)) {
- addr_spec();
- } else {
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 6:
- angle_addr();
- break;
- case DOTATOM:
- case QUOTEDSTRING:
- name_addr();
- break;
- default:
- jj_la1[6] = jj_gen;
- jj_consume_token(-1);
- throw new ParseException();
- }
- }
- } catch (Throwable jjte000) {
- if (jjtc000) {
- jjtree.clearNodeScope(jjtn000);
- jjtc000 = false;
- } else {
- jjtree.popNode();
- }
- if (jjte000 instanceof RuntimeException) {
- {if (true) throw (RuntimeException)jjte000;}
- }
- if (jjte000 instanceof ParseException) {
- {if (true) throw (ParseException)jjte000;}
- }
- {if (true) throw (Error)jjte000;}
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
- }
-
- final public void name_addr() throws ParseException {
- /*@bgen(jjtree) name_addr */
- ASTname_addr jjtn000 = new ASTname_addr(JJTNAME_ADDR);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
- try {
- phrase();
- angle_addr();
- } catch (Throwable jjte000) {
- if (jjtc000) {
- jjtree.clearNodeScope(jjtn000);
- jjtc000 = false;
- } else {
- jjtree.popNode();
- }
- if (jjte000 instanceof RuntimeException) {
- {if (true) throw (RuntimeException)jjte000;}
- }
- if (jjte000 instanceof ParseException) {
- {if (true) throw (ParseException)jjte000;}
- }
- {if (true) throw (Error)jjte000;}
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
- }
-
- final public void group_body() throws ParseException {
- /*@bgen(jjtree) group_body */
- ASTgroup_body jjtn000 = new ASTgroup_body(JJTGROUP_BODY);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
- try {
- jj_consume_token(4);
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 6:
- case DOTATOM:
- case QUOTEDSTRING:
- mailbox();
- break;
- default:
- jj_la1[7] = jj_gen;
- ;
- }
- label_2:
- while (true) {
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 3:
- ;
- break;
- default:
- jj_la1[8] = jj_gen;
- break label_2;
- }
- jj_consume_token(3);
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 6:
- case DOTATOM:
- case QUOTEDSTRING:
- mailbox();
- break;
- default:
- jj_la1[9] = jj_gen;
- ;
- }
- }
- jj_consume_token(5);
- } catch (Throwable jjte000) {
- if (jjtc000) {
- jjtree.clearNodeScope(jjtn000);
- jjtc000 = false;
- } else {
- jjtree.popNode();
- }
- if (jjte000 instanceof RuntimeException) {
- {if (true) throw (RuntimeException)jjte000;}
- }
- if (jjte000 instanceof ParseException) {
- {if (true) throw (ParseException)jjte000;}
- }
- {if (true) throw (Error)jjte000;}
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
- }
-
- final public void angle_addr() throws ParseException {
- /*@bgen(jjtree) angle_addr */
- ASTangle_addr jjtn000 = new ASTangle_addr(JJTANGLE_ADDR);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
- try {
- jj_consume_token(6);
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 8:
- route();
- break;
- default:
- jj_la1[10] = jj_gen;
- ;
- }
- addr_spec();
- jj_consume_token(7);
- } catch (Throwable jjte000) {
- if (jjtc000) {
- jjtree.clearNodeScope(jjtn000);
- jjtc000 = false;
- } else {
- jjtree.popNode();
- }
- if (jjte000 instanceof RuntimeException) {
- {if (true) throw (RuntimeException)jjte000;}
- }
- if (jjte000 instanceof ParseException) {
- {if (true) throw (ParseException)jjte000;}
- }
- {if (true) throw (Error)jjte000;}
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
- }
-
- final public void route() throws ParseException {
- /*@bgen(jjtree) route */
- ASTroute jjtn000 = new ASTroute(JJTROUTE);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
- try {
- jj_consume_token(8);
- domain();
- label_3:
- while (true) {
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 3:
- case 8:
- ;
- break;
- default:
- jj_la1[11] = jj_gen;
- break label_3;
- }
- label_4:
- while (true) {
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 3:
- ;
- break;
- default:
- jj_la1[12] = jj_gen;
- break label_4;
- }
- jj_consume_token(3);
- }
- jj_consume_token(8);
- domain();
- }
- jj_consume_token(4);
- } catch (Throwable jjte000) {
- if (jjtc000) {
- jjtree.clearNodeScope(jjtn000);
- jjtc000 = false;
- } else {
- jjtree.popNode();
- }
- if (jjte000 instanceof RuntimeException) {
- {if (true) throw (RuntimeException)jjte000;}
- }
- if (jjte000 instanceof ParseException) {
- {if (true) throw (ParseException)jjte000;}
- }
- {if (true) throw (Error)jjte000;}
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
- }
-
- final public void phrase() throws ParseException {
- /*@bgen(jjtree) phrase */
- ASTphrase jjtn000 = new ASTphrase(JJTPHRASE);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
- try {
- label_5:
- while (true) {
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case DOTATOM:
- jj_consume_token(DOTATOM);
- break;
- case QUOTEDSTRING:
- jj_consume_token(QUOTEDSTRING);
- break;
- default:
- jj_la1[13] = jj_gen;
- jj_consume_token(-1);
- throw new ParseException();
- }
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case DOTATOM:
- case QUOTEDSTRING:
- ;
- break;
- default:
- jj_la1[14] = jj_gen;
- break label_5;
- }
- }
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
- }
-
- final public void addr_spec() throws ParseException {
- /*@bgen(jjtree) addr_spec */
- ASTaddr_spec jjtn000 = new ASTaddr_spec(JJTADDR_SPEC);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
- try {
- local_part();
- jj_consume_token(8);
- domain();
- } catch (Throwable jjte000) {
- if (jjtc000) {
- jjtree.clearNodeScope(jjtn000);
- jjtc000 = false;
- } else {
- jjtree.popNode();
- }
- if (jjte000 instanceof RuntimeException) {
- {if (true) throw (RuntimeException)jjte000;}
- }
- if (jjte000 instanceof ParseException) {
- {if (true) throw (ParseException)jjte000;}
- }
- {if (true) throw (Error)jjte000;}
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
- }
-
- final public void local_part() throws ParseException {
- /*@bgen(jjtree) local_part */
- ASTlocal_part jjtn000 = new ASTlocal_part(JJTLOCAL_PART);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);Token t;
- try {
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case DOTATOM:
- t = jj_consume_token(DOTATOM);
- break;
- case QUOTEDSTRING:
- t = jj_consume_token(QUOTEDSTRING);
- break;
- default:
- jj_la1[15] = jj_gen;
- jj_consume_token(-1);
- throw new ParseException();
- }
- label_6:
- while (true) {
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 9:
- case DOTATOM:
- case QUOTEDSTRING:
- ;
- break;
- default:
- jj_la1[16] = jj_gen;
- break label_6;
- }
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 9:
- t = jj_consume_token(9);
- break;
- default:
- jj_la1[17] = jj_gen;
- ;
- }
- if (t.image.charAt(t.image.length() - 1) != '.' || t.kind == AddressListParserConstants.QUOTEDSTRING)
- {if (true) throw new ParseException("Words in local part must be separated by '.'");}
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case DOTATOM:
- t = jj_consume_token(DOTATOM);
- break;
- case QUOTEDSTRING:
- t = jj_consume_token(QUOTEDSTRING);
- break;
- default:
- jj_la1[18] = jj_gen;
- jj_consume_token(-1);
- throw new ParseException();
- }
- }
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
- }
-
- final public void domain() throws ParseException {
- /*@bgen(jjtree) domain */
- ASTdomain jjtn000 = new ASTdomain(JJTDOMAIN);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);Token t;
- try {
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case DOTATOM:
- t = jj_consume_token(DOTATOM);
- label_7:
- while (true) {
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 9:
- case DOTATOM:
- ;
- break;
- default:
- jj_la1[19] = jj_gen;
- break label_7;
- }
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 9:
- t = jj_consume_token(9);
- break;
- default:
- jj_la1[20] = jj_gen;
- ;
- }
- if (t.image.charAt(t.image.length() - 1) != '.')
- {if (true) throw new ParseException("Atoms in domain names must be separated by '.'");}
- t = jj_consume_token(DOTATOM);
- }
- break;
- case DOMAINLITERAL:
- jj_consume_token(DOMAINLITERAL);
- break;
- default:
- jj_la1[21] = jj_gen;
- jj_consume_token(-1);
- throw new ParseException();
- }
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
- }
-
- final private boolean jj_2_1(int xla) {
- jj_la = xla; jj_lastpos = jj_scanpos = token;
- try { return !jj_3_1(); }
- catch(LookaheadSuccess ls) { return true; }
- finally { jj_save(0, xla); }
- }
-
- final private boolean jj_2_2(int xla) {
- jj_la = xla; jj_lastpos = jj_scanpos = token;
- try { return !jj_3_2(); }
- catch(LookaheadSuccess ls) { return true; }
- finally { jj_save(1, xla); }
- }
-
- final private boolean jj_3R_11() {
- Token xsp;
- xsp = jj_scanpos;
- if (jj_scan_token(9)) jj_scanpos = xsp;
- xsp = jj_scanpos;
- if (jj_scan_token(14)) {
- jj_scanpos = xsp;
- if (jj_scan_token(31)) return true;
- }
- return false;
- }
-
- final private boolean jj_3R_13() {
- Token xsp;
- xsp = jj_scanpos;
- if (jj_scan_token(9)) jj_scanpos = xsp;
- if (jj_scan_token(DOTATOM)) return true;
- return false;
- }
-
- final private boolean jj_3R_8() {
- if (jj_3R_9()) return true;
- if (jj_scan_token(8)) return true;
- if (jj_3R_10()) return true;
- return false;
- }
-
- final private boolean jj_3_1() {
- if (jj_3R_8()) return true;
- return false;
- }
-
- final private boolean jj_3R_12() {
- if (jj_scan_token(DOTATOM)) return true;
- Token xsp;
- while (true) {
- xsp = jj_scanpos;
- if (jj_3R_13()) { jj_scanpos = xsp; break; }
- }
- return false;
- }
-
- final private boolean jj_3R_10() {
- Token xsp;
- xsp = jj_scanpos;
- if (jj_3R_12()) {
- jj_scanpos = xsp;
- if (jj_scan_token(18)) return true;
- }
- return false;
- }
-
- final private boolean jj_3_2() {
- if (jj_3R_8()) return true;
- return false;
- }
-
- final private boolean jj_3R_9() {
- Token xsp;
- xsp = jj_scanpos;
- if (jj_scan_token(14)) {
- jj_scanpos = xsp;
- if (jj_scan_token(31)) return true;
- }
- while (true) {
- xsp = jj_scanpos;
- if (jj_3R_11()) { jj_scanpos = xsp; break; }
- }
- return false;
- }
-
- public AddressListParserTokenManager token_source;
- SimpleCharStream jj_input_stream;
- public Token token, jj_nt;
- private int jj_ntk;
- private Token jj_scanpos, jj_lastpos;
- private int jj_la;
- public boolean lookingAhead = false;
- private boolean jj_semLA;
- private int jj_gen;
- final private int[] jj_la1 = new int[22];
- static private int[] jj_la1_0;
- static private int[] jj_la1_1;
- static {
- jj_la1_0();
- jj_la1_1();
- }
- private static void jj_la1_0() {
- jj_la1_0 = new int[] {0x2,0x80004040,0x8,0x80004040,0x50,0x80004040,0x80004040,0x80004040,0x8,0x80004040,0x100,0x108,0x8,0x80004000,0x80004000,0x80004000,0x80004200,0x200,0x80004000,0x4200,0x200,0x44000,};
- }
- private static void jj_la1_1() {
- jj_la1_1 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,};
- }
- final private JJCalls[] jj_2_rtns = new JJCalls[2];
- private boolean jj_rescan = false;
- private int jj_gc = 0;
-
- public AddressListParser(java.io.InputStream stream) {
- this(stream, null);
- }
- public AddressListParser(java.io.InputStream stream, String encoding) {
- try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
- token_source = new AddressListParserTokenManager(jj_input_stream);
- token = new Token();
- jj_ntk = -1;
- jj_gen = 0;
- for (int i = 0; i < 22; i++) jj_la1[i] = -1;
- for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
- }
-
- public void ReInit(java.io.InputStream stream) {
- ReInit(stream, null);
- }
- public void ReInit(java.io.InputStream stream, String encoding) {
- try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
- token_source.ReInit(jj_input_stream);
- token = new Token();
- jj_ntk = -1;
- jjtree.reset();
- jj_gen = 0;
- for (int i = 0; i < 22; i++) jj_la1[i] = -1;
- for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
- }
-
- public AddressListParser(java.io.Reader stream) {
- jj_input_stream = new SimpleCharStream(stream, 1, 1);
- token_source = new AddressListParserTokenManager(jj_input_stream);
- token = new Token();
- jj_ntk = -1;
- jj_gen = 0;
- for (int i = 0; i < 22; i++) jj_la1[i] = -1;
- for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
- }
-
- public void ReInit(java.io.Reader stream) {
- jj_input_stream.ReInit(stream, 1, 1);
- token_source.ReInit(jj_input_stream);
- token = new Token();
- jj_ntk = -1;
- jjtree.reset();
- jj_gen = 0;
- for (int i = 0; i < 22; i++) jj_la1[i] = -1;
- for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
- }
-
- public AddressListParser(AddressListParserTokenManager tm) {
- token_source = tm;
- token = new Token();
- jj_ntk = -1;
- jj_gen = 0;
- for (int i = 0; i < 22; i++) jj_la1[i] = -1;
- for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
- }
-
- public void ReInit(AddressListParserTokenManager tm) {
- token_source = tm;
- token = new Token();
- jj_ntk = -1;
- jjtree.reset();
- jj_gen = 0;
- for (int i = 0; i < 22; i++) jj_la1[i] = -1;
- for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
- }
-
- final private Token jj_consume_token(int kind) throws ParseException {
- Token oldToken;
- if ((oldToken = token).next != null) token = token.next;
- else token = token.next = token_source.getNextToken();
- jj_ntk = -1;
- if (token.kind == kind) {
- jj_gen++;
- if (++jj_gc > 100) {
- jj_gc = 0;
- for (int i = 0; i < jj_2_rtns.length; i++) {
- JJCalls c = jj_2_rtns[i];
- while (c != null) {
- if (c.gen < jj_gen) c.first = null;
- c = c.next;
- }
- }
- }
- return token;
- }
- token = oldToken;
- jj_kind = kind;
- throw generateParseException();
- }
-
- static private final class LookaheadSuccess extends java.lang.Error { }
- final private LookaheadSuccess jj_ls = new LookaheadSuccess();
- final private boolean jj_scan_token(int kind) {
- if (jj_scanpos == jj_lastpos) {
- jj_la--;
- if (jj_scanpos.next == null) {
- jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
- } else {
- jj_lastpos = jj_scanpos = jj_scanpos.next;
- }
- } else {
- jj_scanpos = jj_scanpos.next;
- }
- if (jj_rescan) {
- int i = 0; Token tok = token;
- while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
- if (tok != null) jj_add_error_token(kind, i);
- }
- if (jj_scanpos.kind != kind) return true;
- if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
- return false;
- }
-
- final public Token getNextToken() {
- if (token.next != null) token = token.next;
- else token = token.next = token_source.getNextToken();
- jj_ntk = -1;
- jj_gen++;
- return token;
- }
-
- final public Token getToken(int index) {
- Token t = lookingAhead ? jj_scanpos : token;
- for (int i = 0; i < index; i++) {
- if (t.next != null) t = t.next;
- else t = t.next = token_source.getNextToken();
- }
- return t;
- }
-
- final private int jj_ntk() {
- if ((jj_nt=token.next) == null)
- return (jj_ntk = (token.next=token_source.getNextToken()).kind);
- else
- return (jj_ntk = jj_nt.kind);
- }
-
- private java.util.Vector jj_expentries = new java.util.Vector();
- private int[] jj_expentry;
- private int jj_kind = -1;
- private int[] jj_lasttokens = new int[100];
- private int jj_endpos;
-
- private void jj_add_error_token(int kind, int pos) {
- if (pos >= 100) return;
- if (pos == jj_endpos + 1) {
- jj_lasttokens[jj_endpos++] = kind;
- } else if (jj_endpos != 0) {
- jj_expentry = new int[jj_endpos];
- for (int i = 0; i < jj_endpos; i++) {
- jj_expentry[i] = jj_lasttokens[i];
- }
- boolean exists = false;
- for (java.util.Enumeration e = jj_expentries.elements(); e.hasMoreElements();) {
- int[] oldentry = (int[])(e.nextElement());
- if (oldentry.length == jj_expentry.length) {
- exists = true;
- for (int i = 0; i < jj_expentry.length; i++) {
- if (oldentry[i] != jj_expentry[i]) {
- exists = false;
- break;
- }
- }
- if (exists) break;
- }
- }
- if (!exists) jj_expentries.addElement(jj_expentry);
- if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
- }
- }
-
- public ParseException generateParseException() {
- jj_expentries.removeAllElements();
- boolean[] la1tokens = new boolean[34];
- for (int i = 0; i < 34; i++) {
- la1tokens[i] = false;
- }
- if (jj_kind >= 0) {
- la1tokens[jj_kind] = true;
- jj_kind = -1;
- }
- for (int i = 0; i < 22; i++) {
- if (jj_la1[i] == jj_gen) {
- for (int j = 0; j < 32; j++) {
- if ((jj_la1_0[i] & (1<<j)) != 0) {
- la1tokens[j] = true;
- }
- if ((jj_la1_1[i] & (1<<j)) != 0) {
- la1tokens[32+j] = true;
- }
- }
- }
- }
- for (int i = 0; i < 34; i++) {
- if (la1tokens[i]) {
- jj_expentry = new int[1];
- jj_expentry[0] = i;
- jj_expentries.addElement(jj_expentry);
- }
- }
- jj_endpos = 0;
- jj_rescan_token();
- jj_add_error_token(0, 0);
- int[][] exptokseq = new int[jj_expentries.size()][];
- for (int i = 0; i < jj_expentries.size(); i++) {
- exptokseq[i] = (int[])jj_expentries.elementAt(i);
- }
- return new ParseException(token, exptokseq, tokenImage);
- }
-
- final public void enable_tracing() {
- }
-
- final public void disable_tracing() {
- }
-
- final private void jj_rescan_token() {
- jj_rescan = true;
- for (int i = 0; i < 2; i++) {
- try {
- JJCalls p = jj_2_rtns[i];
- do {
- if (p.gen > jj_gen) {
- jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
- switch (i) {
- case 0: jj_3_1(); break;
- case 1: jj_3_2(); break;
- }
- }
- p = p.next;
- } while (p != null);
- } catch(LookaheadSuccess ls) { }
- }
- jj_rescan = false;
- }
-
- final private void jj_save(int index, int xla) {
- JJCalls p = jj_2_rtns[index];
- while (p.gen > jj_gen) {
- if (p.next == null) { p = p.next = new JJCalls(); break; }
- p = p.next;
- }
- p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
- }
-
- static final class JJCalls {
- int gen;
- Token first;
- int arg;
- JJCalls next;
- }
-
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/AddressListParser.jj b/src/org/apache/james/mime4j/field/address/parser/AddressListParser.jj
deleted file mode 100644
index 685988634..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/AddressListParser.jj
+++ /dev/null
@@ -1,595 +0,0 @@
-/*@bgen(jjtree) Generated By:JJTree: Do not edit this line. /Users/jason/Projects/apache-mime4j-0.3/target/generated-sources/jjtree/org/apache/james/mime4j/field/address/parser/AddressListParser.jj */
-/*@egen*//****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-
-/**
- * RFC2822 address list parser.
- *
- * Created 9/17/2004
- * by Joe Cheng <code@joecheng.com>
- */
-
-options {
- STATIC=false;
- LOOKAHEAD=1;
- //DEBUG_PARSER=true;
- //DEBUG_TOKEN_MANAGER=true;
-}
-
-PARSER_BEGIN(AddressListParser)
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.address.parser;
-
-public class AddressListParser/*@bgen(jjtree)*/implements AddressListParserTreeConstants/*@egen*/ {/*@bgen(jjtree)*/
- protected JJTAddressListParserState jjtree = new JJTAddressListParserState();
-
-/*@egen*/
- public static void main(String args[]) throws ParseException {
- while (true) {
- try {
- AddressListParser parser = new AddressListParser(System.in);
- parser.parseLine();
- ((SimpleNode)parser.jjtree.rootNode()).dump("> ");
- } catch (Exception x) {
- x.printStackTrace();
- return;
- }
- }
- }
-
- private static void log(String msg) {
- System.out.print(msg);
- }
-
- public ASTaddress_list parse() throws ParseException {
- try {
- parseAll();
- return (ASTaddress_list)jjtree.rootNode();
- } catch (TokenMgrError tme) {
- throw new ParseException(tme.getMessage());
- }
- }
-
-
- void jjtreeOpenNodeScope(Node n) {
- ((SimpleNode)n).firstToken = getToken(1);
- }
-
- void jjtreeCloseNodeScope(Node n) {
- ((SimpleNode)n).lastToken = getToken(0);
- }
-}
-
-PARSER_END(AddressListParser)
-
-void parseLine() :
-{}
-{
- address_list() ["\r"] "\n"
-}
-
-void parseAll() :
-{}
-{
- address_list() <EOF>
-}
-
-void address_list() :
-{/*@bgen(jjtree) address_list */
- ASTaddress_list jjtn000 = new ASTaddress_list(JJTADDRESS_LIST);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
-/*@egen*/}
-{/*@bgen(jjtree) address_list */
- try {
-/*@egen*/
- [ address() ]
- (
- ","
- [ address() ]
- )*/*@bgen(jjtree)*/
- } catch (Throwable jjte000) {
- if (jjtc000) {
- jjtree.clearNodeScope(jjtn000);
- jjtc000 = false;
- } else {
- jjtree.popNode();
- }
- if (jjte000 instanceof RuntimeException) {
- throw (RuntimeException)jjte000;
- }
- if (jjte000 instanceof ParseException) {
- throw (ParseException)jjte000;
- }
- throw (Error)jjte000;
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
-/*@egen*/
-}
-
-void address() :
-{/*@bgen(jjtree) address */
- ASTaddress jjtn000 = new ASTaddress(JJTADDRESS);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
-/*@egen*/}
-{/*@bgen(jjtree) address */
- try {
-/*@egen*/
- LOOKAHEAD(2147483647)
- addr_spec()
-| angle_addr()
-| ( phrase() (group_body() | angle_addr()) )/*@bgen(jjtree)*/
- } catch (Throwable jjte000) {
- if (jjtc000) {
- jjtree.clearNodeScope(jjtn000);
- jjtc000 = false;
- } else {
- jjtree.popNode();
- }
- if (jjte000 instanceof RuntimeException) {
- throw (RuntimeException)jjte000;
- }
- if (jjte000 instanceof ParseException) {
- throw (ParseException)jjte000;
- }
- throw (Error)jjte000;
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
-/*@egen*/
-}
-
-void mailbox() :
-{/*@bgen(jjtree) mailbox */
- ASTmailbox jjtn000 = new ASTmailbox(JJTMAILBOX);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
-/*@egen*/}
-{/*@bgen(jjtree) mailbox */
- try {
-/*@egen*/
- LOOKAHEAD(2147483647)
- addr_spec()
-| angle_addr()
-| name_addr()/*@bgen(jjtree)*/
- } catch (Throwable jjte000) {
- if (jjtc000) {
- jjtree.clearNodeScope(jjtn000);
- jjtc000 = false;
- } else {
- jjtree.popNode();
- }
- if (jjte000 instanceof RuntimeException) {
- throw (RuntimeException)jjte000;
- }
- if (jjte000 instanceof ParseException) {
- throw (ParseException)jjte000;
- }
- throw (Error)jjte000;
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
-/*@egen*/
-}
-
-void name_addr() :
-{/*@bgen(jjtree) name_addr */
- ASTname_addr jjtn000 = new ASTname_addr(JJTNAME_ADDR);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
-/*@egen*/}
-{/*@bgen(jjtree) name_addr */
- try {
-/*@egen*/
- phrase() angle_addr()/*@bgen(jjtree)*/
- } catch (Throwable jjte000) {
- if (jjtc000) {
- jjtree.clearNodeScope(jjtn000);
- jjtc000 = false;
- } else {
- jjtree.popNode();
- }
- if (jjte000 instanceof RuntimeException) {
- throw (RuntimeException)jjte000;
- }
- if (jjte000 instanceof ParseException) {
- throw (ParseException)jjte000;
- }
- throw (Error)jjte000;
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
-/*@egen*/
-}
-
-void group_body() :
-{/*@bgen(jjtree) group_body */
- ASTgroup_body jjtn000 = new ASTgroup_body(JJTGROUP_BODY);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
-/*@egen*/}
-{/*@bgen(jjtree) group_body */
- try {
-/*@egen*/
- ":"
- [ mailbox() ]
- (
- ","
- [ mailbox() ]
- )*
- ";"/*@bgen(jjtree)*/
- } catch (Throwable jjte000) {
- if (jjtc000) {
- jjtree.clearNodeScope(jjtn000);
- jjtc000 = false;
- } else {
- jjtree.popNode();
- }
- if (jjte000 instanceof RuntimeException) {
- throw (RuntimeException)jjte000;
- }
- if (jjte000 instanceof ParseException) {
- throw (ParseException)jjte000;
- }
- throw (Error)jjte000;
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
-/*@egen*/
-}
-
-void angle_addr() :
-{/*@bgen(jjtree) angle_addr */
- ASTangle_addr jjtn000 = new ASTangle_addr(JJTANGLE_ADDR);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
-/*@egen*/}
-{/*@bgen(jjtree) angle_addr */
- try {
-/*@egen*/
- "<" [ route() ] addr_spec() ">"/*@bgen(jjtree)*/
- } catch (Throwable jjte000) {
- if (jjtc000) {
- jjtree.clearNodeScope(jjtn000);
- jjtc000 = false;
- } else {
- jjtree.popNode();
- }
- if (jjte000 instanceof RuntimeException) {
- throw (RuntimeException)jjte000;
- }
- if (jjte000 instanceof ParseException) {
- throw (ParseException)jjte000;
- }
- throw (Error)jjte000;
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
-/*@egen*/
-}
-
-void route() :
-{/*@bgen(jjtree) route */
- ASTroute jjtn000 = new ASTroute(JJTROUTE);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
-/*@egen*/}
-{/*@bgen(jjtree) route */
- try {
-/*@egen*/
- "@" domain() ( (",")* "@" domain() )* ":"/*@bgen(jjtree)*/
- } catch (Throwable jjte000) {
- if (jjtc000) {
- jjtree.clearNodeScope(jjtn000);
- jjtc000 = false;
- } else {
- jjtree.popNode();
- }
- if (jjte000 instanceof RuntimeException) {
- throw (RuntimeException)jjte000;
- }
- if (jjte000 instanceof ParseException) {
- throw (ParseException)jjte000;
- }
- throw (Error)jjte000;
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
-/*@egen*/
-}
-
-void phrase() :
-{/*@bgen(jjtree) phrase */
- ASTphrase jjtn000 = new ASTphrase(JJTPHRASE);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
-/*@egen*/}
-{/*@bgen(jjtree) phrase */
-try {
-/*@egen*/
-( <DOTATOM>
-| <QUOTEDSTRING>
-)+/*@bgen(jjtree)*/
-} finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
-}
-/*@egen*/
-}
-
-void addr_spec() :
-{/*@bgen(jjtree) addr_spec */
- ASTaddr_spec jjtn000 = new ASTaddr_spec(JJTADDR_SPEC);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
-/*@egen*/}
-{/*@bgen(jjtree) addr_spec */
- try {
-/*@egen*/
- ( local_part() "@" domain() )/*@bgen(jjtree)*/
- } catch (Throwable jjte000) {
- if (jjtc000) {
- jjtree.clearNodeScope(jjtn000);
- jjtc000 = false;
- } else {
- jjtree.popNode();
- }
- if (jjte000 instanceof RuntimeException) {
- throw (RuntimeException)jjte000;
- }
- if (jjte000 instanceof ParseException) {
- throw (ParseException)jjte000;
- }
- throw (Error)jjte000;
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
-/*@egen*/
-}
-
-void local_part() :
-{/*@bgen(jjtree) local_part */
- ASTlocal_part jjtn000 = new ASTlocal_part(JJTLOCAL_PART);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
-/*@egen*/ Token t; }
-{/*@bgen(jjtree) local_part */
- try {
-/*@egen*/
- ( t=<DOTATOM> | t=<QUOTEDSTRING> )
- ( [t="."]
- {
- if (t.image.charAt(t.image.length() - 1) != '.' || t.kind == AddressListParserConstants.QUOTEDSTRING)
- throw new ParseException("Words in local part must be separated by '.'");
- }
- ( t=<DOTATOM> | t=<QUOTEDSTRING> )
- )*/*@bgen(jjtree)*/
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
-/*@egen*/
-}
-
-void domain() :
-{/*@bgen(jjtree) domain */
- ASTdomain jjtn000 = new ASTdomain(JJTDOMAIN);
- boolean jjtc000 = true;
- jjtree.openNodeScope(jjtn000);
- jjtreeOpenNodeScope(jjtn000);
-/*@egen*/ Token t; }
-{/*@bgen(jjtree) domain */
- try {
-/*@egen*/
- ( t=<DOTATOM>
- ( [t="."]
- {
- if (t.image.charAt(t.image.length() - 1) != '.')
- throw new ParseException("Atoms in domain names must be separated by '.'");
- }
- t=<DOTATOM>
- )*
- )
-| <DOMAINLITERAL>/*@bgen(jjtree)*/
- } finally {
- if (jjtc000) {
- jjtree.closeNodeScope(jjtn000, true);
- jjtreeCloseNodeScope(jjtn000);
- }
- }
-/*@egen*/
-}
-
-SPECIAL_TOKEN :
-{
- < WS: ( [" ", "\t"] )+ >
-}
-
-TOKEN :
-{
- < #ALPHA: ["a" - "z", "A" - "Z"] >
-| < #DIGIT: ["0" - "9"] >
-| < #ATEXT: ( <ALPHA> | <DIGIT>
- | "!" | "#" | "$" | "%"
- | "&" | "'" | "*" | "+"
- | "-" | "/" | "=" | "?"
- | "^" | "_" | "`" | "{"
- | "|" | "}" | "~"
- )>
-| < DOTATOM: <ATEXT> ( <ATEXT> | "." )* >
-}
-
-TOKEN_MGR_DECLS :
-{
- // Keeps track of how many levels of comment nesting
- // we've encountered. This is only used when the 2nd
- // level is reached, for example ((this)), not (this).
- // This is because the outermost level must be treated
- // specially anyway, because the outermost ")" has a
- // different token type than inner ")" instances.
- static int commentNest;
-}
-
-MORE :
-{
- // domain literal
- "[" : INDOMAINLITERAL
-}
-
-<INDOMAINLITERAL>
-MORE :
-{
- < <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); }
-| < ~["[", "]", "\\"] >
-}
-
-<INDOMAINLITERAL>
-TOKEN :
-{
- < DOMAINLITERAL: "]" > { matchedToken.image = image.toString(); }: DEFAULT
-}
-
-MORE :
-{
- // starts a comment
- "(" : INCOMMENT
-}
-
-<INCOMMENT>
-SKIP :
-{
- // ends a comment
- < COMMENT: ")" > : DEFAULT
- // if this is ever changed to not be a SKIP, need
- // to make sure matchedToken.token = token.toString()
- // is called.
-}
-
-<INCOMMENT>
-MORE :
-{
- < <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); }
-| "(" { commentNest = 1; } : NESTED_COMMENT
-| < <ANY>>
-}
-
-<NESTED_COMMENT>
-MORE :
-{
- < <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); }
-| "(" { ++commentNest; }
-| ")" { --commentNest; if (commentNest == 0) SwitchTo(INCOMMENT); }
-| < <ANY>>
-}
-
-
-// QUOTED STRINGS
-
-MORE :
-{
- "\"" { image.deleteCharAt(image.length() - 1); } : INQUOTEDSTRING
-}
-
-<INQUOTEDSTRING>
-MORE :
-{
- < <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); }
-| < (~["\"", "\\"])+ >
-}
-
-<INQUOTEDSTRING>
-TOKEN :
-{
- < QUOTEDSTRING: "\"" > { matchedToken.image = image.substring(0, image.length() - 1); } : DEFAULT
-}
-
-// GLOBALS
-
-<*>
-TOKEN :
-{
- < #QUOTEDPAIR: "\\" <ANY> >
-| < #ANY: ~[] >
-}
-
-// ERROR!
-/*
-
-<*>
-TOKEN :
-{
- < UNEXPECTED_CHAR: <ANY> >
-}
-
-*/ \ No newline at end of file
diff --git a/src/org/apache/james/mime4j/field/address/parser/AddressListParserConstants.java b/src/org/apache/james/mime4j/field/address/parser/AddressListParserConstants.java
deleted file mode 100644
index a21ad35db..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/AddressListParserConstants.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/* Generated By:JJTree&JavaCC: Do not edit this line. AddressListParserConstants.java */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.address.parser;
-
-public interface AddressListParserConstants {
-
- int EOF = 0;
- int WS = 10;
- int ALPHA = 11;
- int DIGIT = 12;
- int ATEXT = 13;
- int DOTATOM = 14;
- int DOMAINLITERAL = 18;
- int COMMENT = 20;
- int QUOTEDSTRING = 31;
- int QUOTEDPAIR = 32;
- int ANY = 33;
-
- int DEFAULT = 0;
- int INDOMAINLITERAL = 1;
- int INCOMMENT = 2;
- int NESTED_COMMENT = 3;
- int INQUOTEDSTRING = 4;
-
- String[] tokenImage = {
- "<EOF>",
- "\"\\r\"",
- "\"\\n\"",
- "\",\"",
- "\":\"",
- "\";\"",
- "\"<\"",
- "\">\"",
- "\"@\"",
- "\".\"",
- "<WS>",
- "<ALPHA>",
- "<DIGIT>",
- "<ATEXT>",
- "<DOTATOM>",
- "\"[\"",
- "<token of kind 16>",
- "<token of kind 17>",
- "\"]\"",
- "\"(\"",
- "\")\"",
- "<token of kind 21>",
- "\"(\"",
- "<token of kind 23>",
- "<token of kind 24>",
- "\"(\"",
- "\")\"",
- "<token of kind 27>",
- "\"\\\"\"",
- "<token of kind 29>",
- "<token of kind 30>",
- "\"\\\"\"",
- "<QUOTEDPAIR>",
- "<ANY>",
- };
-
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/AddressListParserTokenManager.java b/src/org/apache/james/mime4j/field/address/parser/AddressListParserTokenManager.java
deleted file mode 100644
index df8974a3b..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/AddressListParserTokenManager.java
+++ /dev/null
@@ -1,1009 +0,0 @@
-/* Generated By:JJTree&JavaCC: Do not edit this line. AddressListParserTokenManager.java */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.address.parser;
-
-public class AddressListParserTokenManager implements AddressListParserConstants
-{
- // Keeps track of how many levels of comment nesting
- // we've encountered. This is only used when the 2nd
- // level is reached, for example ((this)), not (this).
- // This is because the outermost level must be treated
- // specially anyway, because the outermost ")" has a
- // different token type than inner ")" instances.
- static int commentNest;
- public java.io.PrintStream debugStream = System.out;
- public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
-private final int jjStopStringLiteralDfa_0(int pos, long active0)
-{
- switch (pos)
- {
- default :
- return -1;
- }
-}
-private final int jjStartNfa_0(int pos, long active0)
-{
- return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
-}
-private final int jjStopAtPos(int pos, int kind)
-{
- jjmatchedKind = kind;
- jjmatchedPos = pos;
- return pos + 1;
-}
-private final int jjStartNfaWithStates_0(int pos, int kind, int state)
-{
- jjmatchedKind = kind;
- jjmatchedPos = pos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return pos + 1; }
- return jjMoveNfa_0(state, pos + 1);
-}
-private final int jjMoveStringLiteralDfa0_0()
-{
- switch(curChar)
- {
- case 10:
- return jjStopAtPos(0, 2);
- case 13:
- return jjStopAtPos(0, 1);
- case 34:
- return jjStopAtPos(0, 28);
- case 40:
- return jjStopAtPos(0, 19);
- case 44:
- return jjStopAtPos(0, 3);
- case 46:
- return jjStopAtPos(0, 9);
- case 58:
- return jjStopAtPos(0, 4);
- case 59:
- return jjStopAtPos(0, 5);
- case 60:
- return jjStopAtPos(0, 6);
- case 62:
- return jjStopAtPos(0, 7);
- case 64:
- return jjStopAtPos(0, 8);
- case 91:
- return jjStopAtPos(0, 15);
- default :
- return jjMoveNfa_0(1, 0);
- }
-}
-private final void jjCheckNAdd(int state)
-{
- if (jjrounds[state] != jjround)
- {
- jjstateSet[jjnewStateCnt++] = state;
- jjrounds[state] = jjround;
- }
-}
-private final void jjAddStates(int start, int end)
-{
- do {
- jjstateSet[jjnewStateCnt++] = jjnextStates[start];
- } while (start++ != end);
-}
-private final void jjCheckNAddTwoStates(int state1, int state2)
-{
- jjCheckNAdd(state1);
- jjCheckNAdd(state2);
-}
-private final void jjCheckNAddStates(int start, int end)
-{
- do {
- jjCheckNAdd(jjnextStates[start]);
- } while (start++ != end);
-}
-private final void jjCheckNAddStates(int start)
-{
- jjCheckNAdd(jjnextStates[start]);
- jjCheckNAdd(jjnextStates[start + 1]);
-}
-private final int jjMoveNfa_0(int startState, int curPos)
-{
- int[] nextStates;
- int startsAt = 0;
- jjnewStateCnt = 3;
- int i = 1;
- jjstateSet[0] = startState;
- int j, kind = 0x7fffffff;
- for (;;)
- {
- if (++jjround == 0x7fffffff)
- ReInitRounds();
- if (curChar < 64)
- {
- long l = 1L << curChar;
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 1:
- if ((0xa3ffacfa00000000L & l) != 0L)
- {
- if (kind > 14)
- kind = 14;
- jjCheckNAdd(2);
- }
- else if ((0x100000200L & l) != 0L)
- {
- if (kind > 10)
- kind = 10;
- jjCheckNAdd(0);
- }
- break;
- case 0:
- if ((0x100000200L & l) == 0L)
- break;
- kind = 10;
- jjCheckNAdd(0);
- break;
- case 2:
- if ((0xa3ffecfa00000000L & l) == 0L)
- break;
- if (kind > 14)
- kind = 14;
- jjCheckNAdd(2);
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else if (curChar < 128)
- {
- long l = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 1:
- case 2:
- if ((0x7fffffffc7fffffeL & l) == 0L)
- break;
- if (kind > 14)
- kind = 14;
- jjCheckNAdd(2);
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else
- {
- int i2 = (curChar & 0xff) >> 6;
- long l2 = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- default : break;
- }
- } while(i != startsAt);
- }
- if (kind != 0x7fffffff)
- {
- jjmatchedKind = kind;
- jjmatchedPos = curPos;
- kind = 0x7fffffff;
- }
- ++curPos;
- if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
- return curPos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return curPos; }
- }
-}
-private final int jjStopStringLiteralDfa_2(int pos, long active0)
-{
- switch (pos)
- {
- default :
- return -1;
- }
-}
-private final int jjStartNfa_2(int pos, long active0)
-{
- return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1);
-}
-private final int jjStartNfaWithStates_2(int pos, int kind, int state)
-{
- jjmatchedKind = kind;
- jjmatchedPos = pos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return pos + 1; }
- return jjMoveNfa_2(state, pos + 1);
-}
-private final int jjMoveStringLiteralDfa0_2()
-{
- switch(curChar)
- {
- case 40:
- return jjStopAtPos(0, 22);
- case 41:
- return jjStopAtPos(0, 20);
- default :
- return jjMoveNfa_2(0, 0);
- }
-}
-static final long[] jjbitVec0 = {
- 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
-};
-private final int jjMoveNfa_2(int startState, int curPos)
-{
- int[] nextStates;
- int startsAt = 0;
- jjnewStateCnt = 3;
- int i = 1;
- jjstateSet[0] = startState;
- int j, kind = 0x7fffffff;
- for (;;)
- {
- if (++jjround == 0x7fffffff)
- ReInitRounds();
- if (curChar < 64)
- {
- long l = 1L << curChar;
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if (kind > 23)
- kind = 23;
- break;
- case 1:
- if (kind > 21)
- kind = 21;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else if (curChar < 128)
- {
- long l = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if (kind > 23)
- kind = 23;
- if (curChar == 92)
- jjstateSet[jjnewStateCnt++] = 1;
- break;
- case 1:
- if (kind > 21)
- kind = 21;
- break;
- case 2:
- if (kind > 23)
- kind = 23;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else
- {
- int i2 = (curChar & 0xff) >> 6;
- long l2 = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if ((jjbitVec0[i2] & l2) != 0L && kind > 23)
- kind = 23;
- break;
- case 1:
- if ((jjbitVec0[i2] & l2) != 0L && kind > 21)
- kind = 21;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- if (kind != 0x7fffffff)
- {
- jjmatchedKind = kind;
- jjmatchedPos = curPos;
- kind = 0x7fffffff;
- }
- ++curPos;
- if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
- return curPos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return curPos; }
- }
-}
-private final int jjStopStringLiteralDfa_4(int pos, long active0)
-{
- switch (pos)
- {
- default :
- return -1;
- }
-}
-private final int jjStartNfa_4(int pos, long active0)
-{
- return jjMoveNfa_4(jjStopStringLiteralDfa_4(pos, active0), pos + 1);
-}
-private final int jjStartNfaWithStates_4(int pos, int kind, int state)
-{
- jjmatchedKind = kind;
- jjmatchedPos = pos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return pos + 1; }
- return jjMoveNfa_4(state, pos + 1);
-}
-private final int jjMoveStringLiteralDfa0_4()
-{
- switch(curChar)
- {
- case 34:
- return jjStopAtPos(0, 31);
- default :
- return jjMoveNfa_4(0, 0);
- }
-}
-private final int jjMoveNfa_4(int startState, int curPos)
-{
- int[] nextStates;
- int startsAt = 0;
- jjnewStateCnt = 3;
- int i = 1;
- jjstateSet[0] = startState;
- int j, kind = 0x7fffffff;
- for (;;)
- {
- if (++jjround == 0x7fffffff)
- ReInitRounds();
- if (curChar < 64)
- {
- long l = 1L << curChar;
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- case 2:
- if ((0xfffffffbffffffffL & l) == 0L)
- break;
- if (kind > 30)
- kind = 30;
- jjCheckNAdd(2);
- break;
- case 1:
- if (kind > 29)
- kind = 29;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else if (curChar < 128)
- {
- long l = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if ((0xffffffffefffffffL & l) != 0L)
- {
- if (kind > 30)
- kind = 30;
- jjCheckNAdd(2);
- }
- else if (curChar == 92)
- jjstateSet[jjnewStateCnt++] = 1;
- break;
- case 1:
- if (kind > 29)
- kind = 29;
- break;
- case 2:
- if ((0xffffffffefffffffL & l) == 0L)
- break;
- if (kind > 30)
- kind = 30;
- jjCheckNAdd(2);
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else
- {
- int i2 = (curChar & 0xff) >> 6;
- long l2 = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- case 2:
- if ((jjbitVec0[i2] & l2) == 0L)
- break;
- if (kind > 30)
- kind = 30;
- jjCheckNAdd(2);
- break;
- case 1:
- if ((jjbitVec0[i2] & l2) != 0L && kind > 29)
- kind = 29;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- if (kind != 0x7fffffff)
- {
- jjmatchedKind = kind;
- jjmatchedPos = curPos;
- kind = 0x7fffffff;
- }
- ++curPos;
- if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
- return curPos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return curPos; }
- }
-}
-private final int jjStopStringLiteralDfa_3(int pos, long active0)
-{
- switch (pos)
- {
- default :
- return -1;
- }
-}
-private final int jjStartNfa_3(int pos, long active0)
-{
- return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0), pos + 1);
-}
-private final int jjStartNfaWithStates_3(int pos, int kind, int state)
-{
- jjmatchedKind = kind;
- jjmatchedPos = pos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return pos + 1; }
- return jjMoveNfa_3(state, pos + 1);
-}
-private final int jjMoveStringLiteralDfa0_3()
-{
- switch(curChar)
- {
- case 40:
- return jjStopAtPos(0, 25);
- case 41:
- return jjStopAtPos(0, 26);
- default :
- return jjMoveNfa_3(0, 0);
- }
-}
-private final int jjMoveNfa_3(int startState, int curPos)
-{
- int[] nextStates;
- int startsAt = 0;
- jjnewStateCnt = 3;
- int i = 1;
- jjstateSet[0] = startState;
- int j, kind = 0x7fffffff;
- for (;;)
- {
- if (++jjround == 0x7fffffff)
- ReInitRounds();
- if (curChar < 64)
- {
- long l = 1L << curChar;
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if (kind > 27)
- kind = 27;
- break;
- case 1:
- if (kind > 24)
- kind = 24;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else if (curChar < 128)
- {
- long l = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if (kind > 27)
- kind = 27;
- if (curChar == 92)
- jjstateSet[jjnewStateCnt++] = 1;
- break;
- case 1:
- if (kind > 24)
- kind = 24;
- break;
- case 2:
- if (kind > 27)
- kind = 27;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else
- {
- int i2 = (curChar & 0xff) >> 6;
- long l2 = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if ((jjbitVec0[i2] & l2) != 0L && kind > 27)
- kind = 27;
- break;
- case 1:
- if ((jjbitVec0[i2] & l2) != 0L && kind > 24)
- kind = 24;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- if (kind != 0x7fffffff)
- {
- jjmatchedKind = kind;
- jjmatchedPos = curPos;
- kind = 0x7fffffff;
- }
- ++curPos;
- if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
- return curPos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return curPos; }
- }
-}
-private final int jjStopStringLiteralDfa_1(int pos, long active0)
-{
- switch (pos)
- {
- default :
- return -1;
- }
-}
-private final int jjStartNfa_1(int pos, long active0)
-{
- return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1);
-}
-private final int jjStartNfaWithStates_1(int pos, int kind, int state)
-{
- jjmatchedKind = kind;
- jjmatchedPos = pos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return pos + 1; }
- return jjMoveNfa_1(state, pos + 1);
-}
-private final int jjMoveStringLiteralDfa0_1()
-{
- switch(curChar)
- {
- case 93:
- return jjStopAtPos(0, 18);
- default :
- return jjMoveNfa_1(0, 0);
- }
-}
-private final int jjMoveNfa_1(int startState, int curPos)
-{
- int[] nextStates;
- int startsAt = 0;
- jjnewStateCnt = 3;
- int i = 1;
- jjstateSet[0] = startState;
- int j, kind = 0x7fffffff;
- for (;;)
- {
- if (++jjround == 0x7fffffff)
- ReInitRounds();
- if (curChar < 64)
- {
- long l = 1L << curChar;
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if (kind > 17)
- kind = 17;
- break;
- case 1:
- if (kind > 16)
- kind = 16;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else if (curChar < 128)
- {
- long l = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if ((0xffffffffc7ffffffL & l) != 0L)
- {
- if (kind > 17)
- kind = 17;
- }
- else if (curChar == 92)
- jjstateSet[jjnewStateCnt++] = 1;
- break;
- case 1:
- if (kind > 16)
- kind = 16;
- break;
- case 2:
- if ((0xffffffffc7ffffffL & l) != 0L && kind > 17)
- kind = 17;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else
- {
- int i2 = (curChar & 0xff) >> 6;
- long l2 = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if ((jjbitVec0[i2] & l2) != 0L && kind > 17)
- kind = 17;
- break;
- case 1:
- if ((jjbitVec0[i2] & l2) != 0L && kind > 16)
- kind = 16;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- if (kind != 0x7fffffff)
- {
- jjmatchedKind = kind;
- jjmatchedPos = curPos;
- kind = 0x7fffffff;
- }
- ++curPos;
- if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
- return curPos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return curPos; }
- }
-}
-static final int[] jjnextStates = {
-};
-public static final String[] jjstrLiteralImages = {
-"", "\15", "\12", "\54", "\72", "\73", "\74", "\76", "\100", "\56", null, null,
-null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-null, null, null, null, null, null, null, null, };
-public static final String[] lexStateNames = {
- "DEFAULT",
- "INDOMAINLITERAL",
- "INCOMMENT",
- "NESTED_COMMENT",
- "INQUOTEDSTRING",
-};
-public static final int[] jjnewLexState = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 0, 2, 0, -1, 3, -1, -1,
- -1, -1, -1, 4, -1, -1, 0, -1, -1,
-};
-static final long[] jjtoToken = {
- 0x800443ffL,
-};
-static final long[] jjtoSkip = {
- 0x100400L,
-};
-static final long[] jjtoSpecial = {
- 0x400L,
-};
-static final long[] jjtoMore = {
- 0x7feb8000L,
-};
-protected SimpleCharStream input_stream;
-private final int[] jjrounds = new int[3];
-private final int[] jjstateSet = new int[6];
-StringBuffer image;
-int jjimageLen;
-int lengthOfMatch;
-protected char curChar;
-public AddressListParserTokenManager(SimpleCharStream stream){
- if (SimpleCharStream.staticFlag)
- throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
- input_stream = stream;
-}
-public AddressListParserTokenManager(SimpleCharStream stream, int lexState){
- this(stream);
- SwitchTo(lexState);
-}
-public void ReInit(SimpleCharStream stream)
-{
- jjmatchedPos = jjnewStateCnt = 0;
- curLexState = defaultLexState;
- input_stream = stream;
- ReInitRounds();
-}
-private final void ReInitRounds()
-{
- int i;
- jjround = 0x80000001;
- for (i = 3; i-- > 0;)
- jjrounds[i] = 0x80000000;
-}
-public void ReInit(SimpleCharStream stream, int lexState)
-{
- ReInit(stream);
- SwitchTo(lexState);
-}
-public void SwitchTo(int lexState)
-{
- if (lexState >= 5 || lexState < 0)
- throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
- else
- curLexState = lexState;
-}
-
-protected Token jjFillToken()
-{
- Token t = Token.newToken(jjmatchedKind);
- t.kind = jjmatchedKind;
- String im = jjstrLiteralImages[jjmatchedKind];
- t.image = (im == null) ? input_stream.GetImage() : im;
- t.beginLine = input_stream.getBeginLine();
- t.beginColumn = input_stream.getBeginColumn();
- t.endLine = input_stream.getEndLine();
- t.endColumn = input_stream.getEndColumn();
- return t;
-}
-
-int curLexState = 0;
-int defaultLexState = 0;
-int jjnewStateCnt;
-int jjround;
-int jjmatchedPos;
-int jjmatchedKind;
-
-public Token getNextToken()
-{
- int kind;
- Token specialToken = null;
- Token matchedToken;
- int curPos = 0;
-
- EOFLoop :
- for (;;)
- {
- try
- {
- curChar = input_stream.BeginToken();
- }
- catch(java.io.IOException e)
- {
- jjmatchedKind = 0;
- matchedToken = jjFillToken();
- matchedToken.specialToken = specialToken;
- return matchedToken;
- }
- image = null;
- jjimageLen = 0;
-
- for (;;)
- {
- switch(curLexState)
- {
- case 0:
- jjmatchedKind = 0x7fffffff;
- jjmatchedPos = 0;
- curPos = jjMoveStringLiteralDfa0_0();
- break;
- case 1:
- jjmatchedKind = 0x7fffffff;
- jjmatchedPos = 0;
- curPos = jjMoveStringLiteralDfa0_1();
- break;
- case 2:
- jjmatchedKind = 0x7fffffff;
- jjmatchedPos = 0;
- curPos = jjMoveStringLiteralDfa0_2();
- break;
- case 3:
- jjmatchedKind = 0x7fffffff;
- jjmatchedPos = 0;
- curPos = jjMoveStringLiteralDfa0_3();
- break;
- case 4:
- jjmatchedKind = 0x7fffffff;
- jjmatchedPos = 0;
- curPos = jjMoveStringLiteralDfa0_4();
- break;
- }
- if (jjmatchedKind != 0x7fffffff)
- {
- if (jjmatchedPos + 1 < curPos)
- input_stream.backup(curPos - jjmatchedPos - 1);
- if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
- {
- matchedToken = jjFillToken();
- matchedToken.specialToken = specialToken;
- TokenLexicalActions(matchedToken);
- if (jjnewLexState[jjmatchedKind] != -1)
- curLexState = jjnewLexState[jjmatchedKind];
- return matchedToken;
- }
- else if ((jjtoSkip[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
- {
- if ((jjtoSpecial[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
- {
- matchedToken = jjFillToken();
- if (specialToken == null)
- specialToken = matchedToken;
- else
- {
- matchedToken.specialToken = specialToken;
- specialToken = (specialToken.next = matchedToken);
- }
- }
- if (jjnewLexState[jjmatchedKind] != -1)
- curLexState = jjnewLexState[jjmatchedKind];
- continue EOFLoop;
- }
- MoreLexicalActions();
- if (jjnewLexState[jjmatchedKind] != -1)
- curLexState = jjnewLexState[jjmatchedKind];
- curPos = 0;
- jjmatchedKind = 0x7fffffff;
- try {
- curChar = input_stream.readChar();
- continue;
- }
- catch (java.io.IOException e1) { }
- }
- int error_line = input_stream.getEndLine();
- int error_column = input_stream.getEndColumn();
- String error_after = null;
- boolean EOFSeen = false;
- try { input_stream.readChar(); input_stream.backup(1); }
- catch (java.io.IOException e1) {
- EOFSeen = true;
- error_after = curPos <= 1 ? "" : input_stream.GetImage();
- if (curChar == '\n' || curChar == '\r') {
- error_line++;
- error_column = 0;
- }
- else
- error_column++;
- }
- if (!EOFSeen) {
- input_stream.backup(1);
- error_after = curPos <= 1 ? "" : input_stream.GetImage();
- }
- throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
- }
- }
-}
-
-void MoreLexicalActions()
-{
- jjimageLen += (lengthOfMatch = jjmatchedPos + 1);
- switch(jjmatchedKind)
- {
- case 16 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- image.deleteCharAt(image.length() - 2);
- break;
- case 21 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- image.deleteCharAt(image.length() - 2);
- break;
- case 22 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- commentNest = 1;
- break;
- case 24 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- image.deleteCharAt(image.length() - 2);
- break;
- case 25 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- ++commentNest;
- break;
- case 26 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- --commentNest; if (commentNest == 0) SwitchTo(INCOMMENT);
- break;
- case 28 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- image.deleteCharAt(image.length() - 1);
- break;
- case 29 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- image.deleteCharAt(image.length() - 2);
- break;
- default :
- break;
- }
-}
-void TokenLexicalActions(Token matchedToken)
-{
- switch(jjmatchedKind)
- {
- case 18 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
- matchedToken.image = image.toString();
- break;
- case 31 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
- matchedToken.image = image.substring(0, image.length() - 1);
- break;
- default :
- break;
- }
-}
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/AddressListParserTreeConstants.java b/src/org/apache/james/mime4j/field/address/parser/AddressListParserTreeConstants.java
deleted file mode 100644
index 5987f19d8..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/AddressListParserTreeConstants.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Generated By:JJTree: Do not edit this line. /Users/jason/Projects/apache-mime4j-0.3/target/generated-sources/jjtree/org/apache/james/mime4j/field/address/parser/AddressListParserTreeConstants.java */
-
-package org.apache.james.mime4j.field.address.parser;
-
-public interface AddressListParserTreeConstants
-{
- public int JJTVOID = 0;
- public int JJTADDRESS_LIST = 1;
- public int JJTADDRESS = 2;
- public int JJTMAILBOX = 3;
- public int JJTNAME_ADDR = 4;
- public int JJTGROUP_BODY = 5;
- public int JJTANGLE_ADDR = 6;
- public int JJTROUTE = 7;
- public int JJTPHRASE = 8;
- public int JJTADDR_SPEC = 9;
- public int JJTLOCAL_PART = 10;
- public int JJTDOMAIN = 11;
-
-
- public String[] jjtNodeName = {
- "void",
- "address_list",
- "address",
- "mailbox",
- "name_addr",
- "group_body",
- "angle_addr",
- "route",
- "phrase",
- "addr_spec",
- "local_part",
- "domain",
- };
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/AddressListParserVisitor.java b/src/org/apache/james/mime4j/field/address/parser/AddressListParserVisitor.java
deleted file mode 100644
index 8ec2fe7d2..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/AddressListParserVisitor.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Generated By:JJTree: Do not edit this line. /Users/jason/Projects/apache-mime4j-0.3/target/generated-sources/jjtree/org/apache/james/mime4j/field/address/parser/AddressListParserVisitor.java */
-
-package org.apache.james.mime4j.field.address.parser;
-
-public interface AddressListParserVisitor
-{
- public Object visit(SimpleNode node, Object data);
- public Object visit(ASTaddress_list node, Object data);
- public Object visit(ASTaddress node, Object data);
- public Object visit(ASTmailbox node, Object data);
- public Object visit(ASTname_addr node, Object data);
- public Object visit(ASTgroup_body node, Object data);
- public Object visit(ASTangle_addr node, Object data);
- public Object visit(ASTroute node, Object data);
- public Object visit(ASTphrase node, Object data);
- public Object visit(ASTaddr_spec node, Object data);
- public Object visit(ASTlocal_part node, Object data);
- public Object visit(ASTdomain node, Object data);
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/BaseNode.java b/src/org/apache/james/mime4j/field/address/parser/BaseNode.java
deleted file mode 100644
index 42fe3db0c..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/BaseNode.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field.address.parser;
-
-import org.apache.james.mime4j.field.address.parser.Node;
-import org.apache.james.mime4j.field.address.parser.Token;
-
-public abstract class BaseNode implements Node {
-
- public Token firstToken;
- public Token lastToken;
-
-} \ No newline at end of file
diff --git a/src/org/apache/james/mime4j/field/address/parser/JJTAddressListParserState.java b/src/org/apache/james/mime4j/field/address/parser/JJTAddressListParserState.java
deleted file mode 100644
index cca539483..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/JJTAddressListParserState.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/* Generated By:JJTree: Do not edit this line. /Users/jason/Projects/apache-mime4j-0.3/target/generated-sources/jjtree/org/apache/james/mime4j/field/address/parser/JJTAddressListParserState.java */
-
-package org.apache.james.mime4j.field.address.parser;
-
-class JJTAddressListParserState {
- private java.util.Stack nodes;
- private java.util.Stack marks;
-
- private int sp; // number of nodes on stack
- private int mk; // current mark
- private boolean node_created;
-
- JJTAddressListParserState() {
- nodes = new java.util.Stack();
- marks = new java.util.Stack();
- sp = 0;
- mk = 0;
- }
-
- /* Determines whether the current node was actually closed and
- pushed. This should only be called in the final user action of a
- node scope. */
- boolean nodeCreated() {
- return node_created;
- }
-
- /* Call this to reinitialize the node stack. It is called
- automatically by the parser's ReInit() method. */
- void reset() {
- nodes.removeAllElements();
- marks.removeAllElements();
- sp = 0;
- mk = 0;
- }
-
- /* Returns the root node of the AST. It only makes sense to call
- this after a successful parse. */
- Node rootNode() {
- return (Node)nodes.elementAt(0);
- }
-
- /* Pushes a node on to the stack. */
- void pushNode(Node n) {
- nodes.push(n);
- ++sp;
- }
-
- /* Returns the node on the top of the stack, and remove it from the
- stack. */
- Node popNode() {
- if (--sp < mk) {
- mk = ((Integer)marks.pop()).intValue();
- }
- return (Node)nodes.pop();
- }
-
- /* Returns the node currently on the top of the stack. */
- Node peekNode() {
- return (Node)nodes.peek();
- }
-
- /* Returns the number of children on the stack in the current node
- scope. */
- int nodeArity() {
- return sp - mk;
- }
-
-
- void clearNodeScope(Node n) {
- while (sp > mk) {
- popNode();
- }
- mk = ((Integer)marks.pop()).intValue();
- }
-
-
- void openNodeScope(Node n) {
- marks.push(new Integer(mk));
- mk = sp;
- n.jjtOpen();
- }
-
-
- /* A definite node is constructed from a specified number of
- children. That number of nodes are popped from the stack and
- made the children of the definite node. Then the definite node
- is pushed on to the stack. */
- void closeNodeScope(Node n, int num) {
- mk = ((Integer)marks.pop()).intValue();
- while (num-- > 0) {
- Node c = popNode();
- c.jjtSetParent(n);
- n.jjtAddChild(c, num);
- }
- n.jjtClose();
- pushNode(n);
- node_created = true;
- }
-
-
- /* A conditional node is constructed if its condition is true. All
- the nodes that have been pushed since the node was opened are
- made children of the the conditional node, which is then pushed
- on to the stack. If the condition is false the node is not
- constructed and they are left on the stack. */
- void closeNodeScope(Node n, boolean condition) {
- if (condition) {
- int a = nodeArity();
- mk = ((Integer)marks.pop()).intValue();
- while (a-- > 0) {
- Node c = popNode();
- c.jjtSetParent(n);
- n.jjtAddChild(c, a);
- }
- n.jjtClose();
- pushNode(n);
- node_created = true;
- } else {
- mk = ((Integer)marks.pop()).intValue();
- node_created = false;
- }
- }
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/Node.java b/src/org/apache/james/mime4j/field/address/parser/Node.java
deleted file mode 100644
index 158892016..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/Node.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Generated By:JJTree: Do not edit this line. Node.java */
-
-package org.apache.james.mime4j.field.address.parser;
-
-/* All AST nodes must implement this interface. It provides basic
- machinery for constructing the parent and child relationships
- between nodes. */
-
-public interface Node {
-
- /** This method is called after the node has been made the current
- node. It indicates that child nodes can now be added to it. */
- public void jjtOpen();
-
- /** This method is called after all the child nodes have been
- added. */
- public void jjtClose();
-
- /** This pair of methods are used to inform the node of its
- parent. */
- public void jjtSetParent(Node n);
- public Node jjtGetParent();
-
- /** This method tells the node to add its argument to the node's
- list of children. */
- public void jjtAddChild(Node n, int i);
-
- /** This method returns a child node. The children are numbered
- from zero, left to right. */
- public Node jjtGetChild(int i);
-
- /** Return the number of children the node has. */
- public int jjtGetNumChildren();
-
- /** Accept the visitor. **/
- public Object jjtAccept(AddressListParserVisitor visitor, Object data);
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/ParseException.java b/src/org/apache/james/mime4j/field/address/parser/ParseException.java
deleted file mode 100644
index 939c6cfed..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/ParseException.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.address.parser;
-
-/**
- * This exception is thrown when parse errors are encountered.
- * You can explicitly create objects of this exception type by
- * calling the method generateParseException in the generated
- * parser.
- *
- * You can modify this class to customize your error reporting
- * mechanisms so long as you retain the public fields.
- */
-public class ParseException extends Exception {
-
- /**
- * This constructor is used by the method "generateParseException"
- * in the generated parser. Calling this constructor generates
- * a new object of this type with the fields "currentToken",
- * "expectedTokenSequences", and "tokenImage" set. The boolean
- * flag "specialConstructor" is also set to true to indicate that
- * this constructor was used to create this object.
- * This constructor calls its super class with the empty string
- * to force the "toString" method of parent class "Throwable" to
- * print the error message in the form:
- * ParseException: <result of getMessage>
- */
- public ParseException(Token currentTokenVal,
- int[][] expectedTokenSequencesVal,
- String[] tokenImageVal
- )
- {
- super("");
- specialConstructor = true;
- currentToken = currentTokenVal;
- expectedTokenSequences = expectedTokenSequencesVal;
- tokenImage = tokenImageVal;
- }
-
- /**
- * The following constructors are for use by you for whatever
- * purpose you can think of. Constructing the exception in this
- * manner makes the exception behave in the normal way - i.e., as
- * documented in the class "Throwable". The fields "errorToken",
- * "expectedTokenSequences", and "tokenImage" do not contain
- * relevant information. The JavaCC generated code does not use
- * these constructors.
- */
-
- public ParseException() {
- super();
- specialConstructor = false;
- }
-
- public ParseException(String message) {
- super(message);
- specialConstructor = false;
- }
-
- /**
- * This variable determines which constructor was used to create
- * this object and thereby affects the semantics of the
- * "getMessage" method (see below).
- */
- protected boolean specialConstructor;
-
- /**
- * This is the last token that has been consumed successfully. If
- * this object has been created due to a parse error, the token
- * followng this token will (therefore) be the first error token.
- */
- public Token currentToken;
-
- /**
- * Each entry in this array is an array of integers. Each array
- * of integers represents a sequence of tokens (by their ordinal
- * values) that is expected at this point of the parse.
- */
- public int[][] expectedTokenSequences;
-
- /**
- * This is a reference to the "tokenImage" array of the generated
- * parser within which the parse error occurred. This array is
- * defined in the generated ...Constants interface.
- */
- public String[] tokenImage;
-
- /**
- * This method has the standard behavior when this object has been
- * created using the standard constructors. Otherwise, it uses
- * "currentToken" and "expectedTokenSequences" to generate a parse
- * error message and returns it. If this object has been created
- * due to a parse error, and you do not catch it (it gets thrown
- * from the parser), then this method is called during the printing
- * of the final stack trace, and hence the correct error message
- * gets displayed.
- */
- public String getMessage() {
- if (!specialConstructor) {
- return super.getMessage();
- }
- StringBuffer expected = new StringBuffer();
- int maxSize = 0;
- for (int i = 0; i < expectedTokenSequences.length; i++) {
- if (maxSize < expectedTokenSequences[i].length) {
- maxSize = expectedTokenSequences[i].length;
- }
- for (int j = 0; j < expectedTokenSequences[i].length; j++) {
- expected.append(tokenImage[expectedTokenSequences[i][j]]).append(" ");
- }
- if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
- expected.append("...");
- }
- expected.append(eol).append(" ");
- }
- String retval = "Encountered \"";
- Token tok = currentToken.next;
- for (int i = 0; i < maxSize; i++) {
- if (i != 0) retval += " ";
- if (tok.kind == 0) {
- retval += tokenImage[0];
- break;
- }
- retval += add_escapes(tok.image);
- tok = tok.next;
- }
- retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
- retval += "." + eol;
- if (expectedTokenSequences.length == 1) {
- retval += "Was expecting:" + eol + " ";
- } else {
- retval += "Was expecting one of:" + eol + " ";
- }
- retval += expected.toString();
- return retval;
- }
-
- /**
- * The end of line string for this machine.
- */
- protected String eol = System.getProperty("line.separator", "\n");
-
- /**
- * Used to convert raw characters to their escaped version
- * when these raw version cannot be used as part of an ASCII
- * string literal.
- */
- protected String add_escapes(String str) {
- StringBuffer retval = new StringBuffer();
- char ch;
- for (int i = 0; i < str.length(); i++) {
- switch (str.charAt(i))
- {
- case 0 :
- continue;
- case '\b':
- retval.append("\\b");
- continue;
- case '\t':
- retval.append("\\t");
- continue;
- case '\n':
- retval.append("\\n");
- continue;
- case '\f':
- retval.append("\\f");
- continue;
- case '\r':
- retval.append("\\r");
- continue;
- case '\"':
- retval.append("\\\"");
- continue;
- case '\'':
- retval.append("\\\'");
- continue;
- case '\\':
- retval.append("\\\\");
- continue;
- default:
- if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
- String s = "0000" + Integer.toString(ch, 16);
- retval.append("\\u" + s.substring(s.length() - 4, s.length()));
- } else {
- retval.append(ch);
- }
- continue;
- }
- }
- return retval.toString();
- }
-
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/SimpleCharStream.java b/src/org/apache/james/mime4j/field/address/parser/SimpleCharStream.java
deleted file mode 100644
index 957bbeabc..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/SimpleCharStream.java
+++ /dev/null
@@ -1,454 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.0 */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.address.parser;
-
-/**
- * An implementation of interface CharStream, where the stream is assumed to
- * contain only ASCII characters (without unicode processing).
- */
-
-public class SimpleCharStream
-{
- public static final boolean staticFlag = false;
- int bufsize;
- int available;
- int tokenBegin;
- public int bufpos = -1;
- protected int bufline[];
- protected int bufcolumn[];
-
- protected int column = 0;
- protected int line = 1;
-
- protected boolean prevCharIsCR = false;
- protected boolean prevCharIsLF = false;
-
- protected java.io.Reader inputStream;
-
- protected char[] buffer;
- protected int maxNextCharInd = 0;
- protected int inBuf = 0;
- protected int tabSize = 8;
-
- protected void setTabSize(int i) { tabSize = i; }
- protected int getTabSize(int i) { return tabSize; }
-
-
- protected void ExpandBuff(boolean wrapAround)
- {
- char[] newbuffer = new char[bufsize + 2048];
- int newbufline[] = new int[bufsize + 2048];
- int newbufcolumn[] = new int[bufsize + 2048];
-
- try
- {
- if (wrapAround)
- {
- System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
- System.arraycopy(buffer, 0, newbuffer,
- bufsize - tokenBegin, bufpos);
- buffer = newbuffer;
-
- System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
- System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
- bufline = newbufline;
-
- System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
- System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
- bufcolumn = newbufcolumn;
-
- maxNextCharInd = (bufpos += (bufsize - tokenBegin));
- }
- else
- {
- System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
- buffer = newbuffer;
-
- System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
- bufline = newbufline;
-
- System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
- bufcolumn = newbufcolumn;
-
- maxNextCharInd = (bufpos -= tokenBegin);
- }
- }
- catch (Throwable t)
- {
- throw new Error(t.getMessage());
- }
-
-
- bufsize += 2048;
- available = bufsize;
- tokenBegin = 0;
- }
-
- protected void FillBuff() throws java.io.IOException
- {
- if (maxNextCharInd == available)
- {
- if (available == bufsize)
- {
- if (tokenBegin > 2048)
- {
- bufpos = maxNextCharInd = 0;
- available = tokenBegin;
- }
- else if (tokenBegin < 0)
- bufpos = maxNextCharInd = 0;
- else
- ExpandBuff(false);
- }
- else if (available > tokenBegin)
- available = bufsize;
- else if ((tokenBegin - available) < 2048)
- ExpandBuff(true);
- else
- available = tokenBegin;
- }
-
- int i;
- try {
- if ((i = inputStream.read(buffer, maxNextCharInd,
- available - maxNextCharInd)) == -1)
- {
- inputStream.close();
- throw new java.io.IOException();
- }
- else
- maxNextCharInd += i;
- return;
- }
- catch(java.io.IOException e) {
- --bufpos;
- backup(0);
- if (tokenBegin == -1)
- tokenBegin = bufpos;
- throw e;
- }
- }
-
- public char BeginToken() throws java.io.IOException
- {
- tokenBegin = -1;
- char c = readChar();
- tokenBegin = bufpos;
-
- return c;
- }
-
- protected void UpdateLineColumn(char c)
- {
- column++;
-
- if (prevCharIsLF)
- {
- prevCharIsLF = false;
- line += (column = 1);
- }
- else if (prevCharIsCR)
- {
- prevCharIsCR = false;
- if (c == '\n')
- {
- prevCharIsLF = true;
- }
- else
- line += (column = 1);
- }
-
- switch (c)
- {
- case '\r' :
- prevCharIsCR = true;
- break;
- case '\n' :
- prevCharIsLF = true;
- break;
- case '\t' :
- column--;
- column += (tabSize - (column % tabSize));
- break;
- default :
- break;
- }
-
- bufline[bufpos] = line;
- bufcolumn[bufpos] = column;
- }
-
- public char readChar() throws java.io.IOException
- {
- if (inBuf > 0)
- {
- --inBuf;
-
- if (++bufpos == bufsize)
- bufpos = 0;
-
- return buffer[bufpos];
- }
-
- if (++bufpos >= maxNextCharInd)
- FillBuff();
-
- char c = buffer[bufpos];
-
- UpdateLineColumn(c);
- return (c);
- }
-
- /**
- * @deprecated
- * @see #getEndColumn
- */
-
- public int getColumn() {
- return bufcolumn[bufpos];
- }
-
- /**
- * @deprecated
- * @see #getEndLine
- */
-
- public int getLine() {
- return bufline[bufpos];
- }
-
- public int getEndColumn() {
- return bufcolumn[bufpos];
- }
-
- public int getEndLine() {
- return bufline[bufpos];
- }
-
- public int getBeginColumn() {
- return bufcolumn[tokenBegin];
- }
-
- public int getBeginLine() {
- return bufline[tokenBegin];
- }
-
- public void backup(int amount) {
-
- inBuf += amount;
- if ((bufpos -= amount) < 0)
- bufpos += bufsize;
- }
-
- public SimpleCharStream(java.io.Reader dstream, int startline,
- int startcolumn, int buffersize)
- {
- inputStream = dstream;
- line = startline;
- column = startcolumn - 1;
-
- available = bufsize = buffersize;
- buffer = new char[buffersize];
- bufline = new int[buffersize];
- bufcolumn = new int[buffersize];
- }
-
- public SimpleCharStream(java.io.Reader dstream, int startline,
- int startcolumn)
- {
- this(dstream, startline, startcolumn, 4096);
- }
-
- public SimpleCharStream(java.io.Reader dstream)
- {
- this(dstream, 1, 1, 4096);
- }
- public void ReInit(java.io.Reader dstream, int startline,
- int startcolumn, int buffersize)
- {
- inputStream = dstream;
- line = startline;
- column = startcolumn - 1;
-
- if (buffer == null || buffersize != buffer.length)
- {
- available = bufsize = buffersize;
- buffer = new char[buffersize];
- bufline = new int[buffersize];
- bufcolumn = new int[buffersize];
- }
- prevCharIsLF = prevCharIsCR = false;
- tokenBegin = inBuf = maxNextCharInd = 0;
- bufpos = -1;
- }
-
- public void ReInit(java.io.Reader dstream, int startline,
- int startcolumn)
- {
- ReInit(dstream, startline, startcolumn, 4096);
- }
-
- public void ReInit(java.io.Reader dstream)
- {
- ReInit(dstream, 1, 1, 4096);
- }
- public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
- int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
- {
- this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
- }
-
- public SimpleCharStream(java.io.InputStream dstream, int startline,
- int startcolumn, int buffersize)
- {
- this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
- }
-
- public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
- int startcolumn) throws java.io.UnsupportedEncodingException
- {
- this(dstream, encoding, startline, startcolumn, 4096);
- }
-
- public SimpleCharStream(java.io.InputStream dstream, int startline,
- int startcolumn)
- {
- this(dstream, startline, startcolumn, 4096);
- }
-
- public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
- {
- this(dstream, encoding, 1, 1, 4096);
- }
-
- public SimpleCharStream(java.io.InputStream dstream)
- {
- this(dstream, 1, 1, 4096);
- }
-
- public void ReInit(java.io.InputStream dstream, String encoding, int startline,
- int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
- {
- ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
- }
-
- public void ReInit(java.io.InputStream dstream, int startline,
- int startcolumn, int buffersize)
- {
- ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
- }
-
- public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
- {
- ReInit(dstream, encoding, 1, 1, 4096);
- }
-
- public void ReInit(java.io.InputStream dstream)
- {
- ReInit(dstream, 1, 1, 4096);
- }
- public void ReInit(java.io.InputStream dstream, String encoding, int startline,
- int startcolumn) throws java.io.UnsupportedEncodingException
- {
- ReInit(dstream, encoding, startline, startcolumn, 4096);
- }
- public void ReInit(java.io.InputStream dstream, int startline,
- int startcolumn)
- {
- ReInit(dstream, startline, startcolumn, 4096);
- }
- public String GetImage()
- {
- if (bufpos >= tokenBegin)
- return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
- else
- return new String(buffer, tokenBegin, bufsize - tokenBegin) +
- new String(buffer, 0, bufpos + 1);
- }
-
- public char[] GetSuffix(int len)
- {
- char[] ret = new char[len];
-
- if ((bufpos + 1) >= len)
- System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
- else
- {
- System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
- len - bufpos - 1);
- System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
- }
-
- return ret;
- }
-
- public void Done()
- {
- buffer = null;
- bufline = null;
- bufcolumn = null;
- }
-
- /**
- * Method to adjust line and column numbers for the start of a token.
- */
- public void adjustBeginLineColumn(int newLine, int newCol)
- {
- int start = tokenBegin;
- int len;
-
- if (bufpos >= tokenBegin)
- {
- len = bufpos - tokenBegin + inBuf + 1;
- }
- else
- {
- len = bufsize - tokenBegin + bufpos + 1 + inBuf;
- }
-
- int i = 0, j = 0, k = 0;
- int nextColDiff = 0, columnDiff = 0;
-
- while (i < len &&
- bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
- {
- bufline[j] = newLine;
- nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
- bufcolumn[j] = newCol + columnDiff;
- columnDiff = nextColDiff;
- i++;
- }
-
- if (i < len)
- {
- bufline[j] = newLine++;
- bufcolumn[j] = newCol + columnDiff;
-
- while (i++ < len)
- {
- if (bufline[j = start % bufsize] != bufline[++start % bufsize])
- bufline[j] = newLine++;
- else
- bufline[j] = newLine;
- }
- }
-
- line = bufline[j];
- column = bufcolumn[j];
- }
-
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/SimpleNode.java b/src/org/apache/james/mime4j/field/address/parser/SimpleNode.java
deleted file mode 100644
index 9bf537e60..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/SimpleNode.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Generated By:JJTree: Do not edit this line. SimpleNode.java */
-
-package org.apache.james.mime4j.field.address.parser;
-
-public class SimpleNode extends org.apache.james.mime4j.field.address.parser.BaseNode implements Node {
- protected Node parent;
- protected Node[] children;
- protected int id;
- protected AddressListParser parser;
-
- public SimpleNode(int i) {
- id = i;
- }
-
- public SimpleNode(AddressListParser p, int i) {
- this(i);
- parser = p;
- }
-
- public void jjtOpen() {
- }
-
- public void jjtClose() {
- }
-
- public void jjtSetParent(Node n) { parent = n; }
- public Node jjtGetParent() { return parent; }
-
- public void jjtAddChild(Node n, int i) {
- if (children == null) {
- children = new Node[i + 1];
- } else if (i >= children.length) {
- Node c[] = new Node[i + 1];
- System.arraycopy(children, 0, c, 0, children.length);
- children = c;
- }
- children[i] = n;
- }
-
- public Node jjtGetChild(int i) {
- return children[i];
- }
-
- public int jjtGetNumChildren() {
- return (children == null) ? 0 : children.length;
- }
-
- /** Accept the visitor. **/
- public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
- return visitor.visit(this, data);
- }
-
- /** Accept the visitor. **/
- public Object childrenAccept(AddressListParserVisitor visitor, Object data) {
- if (children != null) {
- for (int i = 0; i < children.length; ++i) {
- children[i].jjtAccept(visitor, data);
- }
- }
- return data;
- }
-
- /* You can override these two methods in subclasses of SimpleNode to
- customize the way the node appears when the tree is dumped. If
- your output uses more than one line you should override
- toString(String), otherwise overriding toString() is probably all
- you need to do. */
-
- public String toString() { return AddressListParserTreeConstants.jjtNodeName[id]; }
- public String toString(String prefix) { return prefix + toString(); }
-
- /* Override this method if you want to customize how the node dumps
- out its children. */
-
- public void dump(String prefix) {
- System.out.println(toString(prefix));
- if (children != null) {
- for (int i = 0; i < children.length; ++i) {
- SimpleNode n = (SimpleNode)children[i];
- if (n != null) {
- n.dump(prefix + " ");
- }
- }
- }
- }
-}
-
diff --git a/src/org/apache/james/mime4j/field/address/parser/Token.java b/src/org/apache/james/mime4j/field/address/parser/Token.java
deleted file mode 100644
index 0228aac3e..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/Token.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.address.parser;
-
-/**
- * Describes the input token stream.
- */
-
-public class Token {
-
- /**
- * An integer that describes the kind of this token. This numbering
- * system is determined by JavaCCParser, and a table of these numbers is
- * stored in the file ...Constants.java.
- */
- public int kind;
-
- /**
- * beginLine and beginColumn describe the position of the first character
- * of this token; endLine and endColumn describe the position of the
- * last character of this token.
- */
- public int beginLine, beginColumn, endLine, endColumn;
-
- /**
- * The string image of the token.
- */
- public String image;
-
- /**
- * A reference to the next regular (non-special) token from the input
- * stream. If this is the last token from the input stream, or if the
- * token manager has not read tokens beyond this one, this field is
- * set to null. This is true only if this token is also a regular
- * token. Otherwise, see below for a description of the contents of
- * this field.
- */
- public Token next;
-
- /**
- * This field is used to access special tokens that occur prior to this
- * token, but after the immediately preceding regular (non-special) token.
- * If there are no such special tokens, this field is set to null.
- * When there are more than one such special token, this field refers
- * to the last of these special tokens, which in turn refers to the next
- * previous special token through its specialToken field, and so on
- * until the first special token (whose specialToken field is null).
- * The next fields of special tokens refer to other special tokens that
- * immediately follow it (without an intervening regular token). If there
- * is no such token, this field is null.
- */
- public Token specialToken;
-
- /**
- * Returns the image.
- */
- public String toString()
- {
- return image;
- }
-
- /**
- * Returns a new Token object, by default. However, if you want, you
- * can create and return subclass objects based on the value of ofKind.
- * Simply add the cases to the switch for all those special cases.
- * For example, if you have a subclass of Token called IDToken that
- * you want to create if ofKind is ID, simlpy add something like :
- *
- * case MyParserConstants.ID : return new IDToken();
- *
- * to the following switch statement. Then you can cast matchedToken
- * variable to the appropriate type and use it in your lexical actions.
- */
- public static final Token newToken(int ofKind)
- {
- switch(ofKind)
- {
- default : return new Token();
- }
- }
-
-}
diff --git a/src/org/apache/james/mime4j/field/address/parser/TokenMgrError.java b/src/org/apache/james/mime4j/field/address/parser/TokenMgrError.java
deleted file mode 100644
index c06a44cf3..000000000
--- a/src/org/apache/james/mime4j/field/address/parser/TokenMgrError.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.address.parser;
-
-public class TokenMgrError extends Error
-{
- /*
- * Ordinals for various reasons why an Error of this type can be thrown.
- */
-
- /**
- * Lexical error occured.
- */
- static final int LEXICAL_ERROR = 0;
-
- /**
- * An attempt wass made to create a second instance of a static token manager.
- */
- static final int STATIC_LEXER_ERROR = 1;
-
- /**
- * Tried to change to an invalid lexical state.
- */
- static final int INVALID_LEXICAL_STATE = 2;
-
- /**
- * Detected (and bailed out of) an infinite loop in the token manager.
- */
- static final int LOOP_DETECTED = 3;
-
- /**
- * Indicates the reason why the exception is thrown. It will have
- * one of the above 4 values.
- */
- int errorCode;
-
- /**
- * Replaces unprintable characters by their espaced (or unicode escaped)
- * equivalents in the given string
- */
- protected static final String addEscapes(String str) {
- StringBuffer retval = new StringBuffer();
- char ch;
- for (int i = 0; i < str.length(); i++) {
- switch (str.charAt(i))
- {
- case 0 :
- continue;
- case '\b':
- retval.append("\\b");
- continue;
- case '\t':
- retval.append("\\t");
- continue;
- case '\n':
- retval.append("\\n");
- continue;
- case '\f':
- retval.append("\\f");
- continue;
- case '\r':
- retval.append("\\r");
- continue;
- case '\"':
- retval.append("\\\"");
- continue;
- case '\'':
- retval.append("\\\'");
- continue;
- case '\\':
- retval.append("\\\\");
- continue;
- default:
- if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
- String s = "0000" + Integer.toString(ch, 16);
- retval.append("\\u" + s.substring(s.length() - 4, s.length()));
- } else {
- retval.append(ch);
- }
- continue;
- }
- }
- return retval.toString();
- }
-
- /**
- * Returns a detailed message for the Error when it is thrown by the
- * token manager to indicate a lexical error.
- * Parameters :
- * EOFSeen : indicates if EOF caused the lexicl error
- * curLexState : lexical state in which this error occured
- * errorLine : line number when the error occured
- * errorColumn : column number when the error occured
- * errorAfter : prefix that was seen before this error occured
- * curchar : the offending character
- * Note: You can customize the lexical error message by modifying this method.
- */
- protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
- return("Lexical error at line " +
- errorLine + ", column " +
- errorColumn + ". Encountered: " +
- (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
- "after : \"" + addEscapes(errorAfter) + "\"");
- }
-
- /**
- * You can also modify the body of this method to customize your error messages.
- * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
- * of end-users concern, so you can return something like :
- *
- * "Internal Error : Please file a bug report .... "
- *
- * from this method for such cases in the release version of your parser.
- */
- public String getMessage() {
- return super.getMessage();
- }
-
- /*
- * Constructors of various flavors follow.
- */
-
- public TokenMgrError() {
- }
-
- public TokenMgrError(String message, int reason) {
- super(message);
- errorCode = reason;
- }
-
- public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
- this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
- }
-}
diff --git a/src/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParser.java b/src/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParser.java
deleted file mode 100644
index 64e829a51..000000000
--- a/src/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParser.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. ContentTypeParser.java */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.contenttype.parser;
-
-import java.util.ArrayList;
-
-public class ContentTypeParser implements ContentTypeParserConstants {
-
- private String type;
- private String subtype;
- private ArrayList paramNames = new ArrayList();
- private ArrayList paramValues = new ArrayList();
-
- public String getType() { return type; }
- public String getSubType() { return subtype; }
- public ArrayList getParamNames() { return paramNames; }
- public ArrayList getParamValues() { return paramValues; }
-
- public static void main(String args[]) throws ParseException {
- while (true) {
- try {
- ContentTypeParser parser = new ContentTypeParser(System.in);
- parser.parseLine();
- } catch (Exception x) {
- x.printStackTrace();
- return;
- }
- }
- }
-
- final public void parseLine() throws ParseException {
- parse();
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 1:
- jj_consume_token(1);
- break;
- default:
- jj_la1[0] = jj_gen;
- ;
- }
- jj_consume_token(2);
- }
-
- final public void parseAll() throws ParseException {
- parse();
- jj_consume_token(0);
- }
-
- final public void parse() throws ParseException {
- Token type;
- Token subtype;
- type = jj_consume_token(ATOKEN);
- jj_consume_token(3);
- subtype = jj_consume_token(ATOKEN);
- this.type = type.image;
- this.subtype = subtype.image;
- label_1:
- while (true) {
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 4:
- ;
- break;
- default:
- jj_la1[1] = jj_gen;
- break label_1;
- }
- jj_consume_token(4);
- parameter();
- }
- }
-
- final public void parameter() throws ParseException {
- Token attrib;
- String val;
- attrib = jj_consume_token(ATOKEN);
- jj_consume_token(5);
- val = value();
- paramNames.add(attrib.image);
- paramValues.add(val);
- }
-
- final public String value() throws ParseException {
- Token t;
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case ATOKEN:
- t = jj_consume_token(ATOKEN);
- break;
- case QUOTEDSTRING:
- t = jj_consume_token(QUOTEDSTRING);
- break;
- default:
- jj_la1[2] = jj_gen;
- jj_consume_token(-1);
- throw new ParseException();
- }
- {if (true) return t.image;}
- throw new Error("Missing return statement in function");
- }
-
- public ContentTypeParserTokenManager token_source;
- SimpleCharStream jj_input_stream;
- public Token token, jj_nt;
- private int jj_ntk;
- private int jj_gen;
- final private int[] jj_la1 = new int[3];
- static private int[] jj_la1_0;
- static {
- jj_la1_0();
- }
- private static void jj_la1_0() {
- jj_la1_0 = new int[] {0x2,0x10,0x280000,};
- }
-
- public ContentTypeParser(java.io.InputStream stream) {
- this(stream, null);
- }
- public ContentTypeParser(java.io.InputStream stream, String encoding) {
- try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
- token_source = new ContentTypeParserTokenManager(jj_input_stream);
- token = new Token();
- jj_ntk = -1;
- jj_gen = 0;
- for (int i = 0; i < 3; i++) jj_la1[i] = -1;
- }
-
- public void ReInit(java.io.InputStream stream) {
- ReInit(stream, null);
- }
- public void ReInit(java.io.InputStream stream, String encoding) {
- try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
- token_source.ReInit(jj_input_stream);
- token = new Token();
- jj_ntk = -1;
- jj_gen = 0;
- for (int i = 0; i < 3; i++) jj_la1[i] = -1;
- }
-
- public ContentTypeParser(java.io.Reader stream) {
- jj_input_stream = new SimpleCharStream(stream, 1, 1);
- token_source = new ContentTypeParserTokenManager(jj_input_stream);
- token = new Token();
- jj_ntk = -1;
- jj_gen = 0;
- for (int i = 0; i < 3; i++) jj_la1[i] = -1;
- }
-
- public void ReInit(java.io.Reader stream) {
- jj_input_stream.ReInit(stream, 1, 1);
- token_source.ReInit(jj_input_stream);
- token = new Token();
- jj_ntk = -1;
- jj_gen = 0;
- for (int i = 0; i < 3; i++) jj_la1[i] = -1;
- }
-
- public ContentTypeParser(ContentTypeParserTokenManager tm) {
- token_source = tm;
- token = new Token();
- jj_ntk = -1;
- jj_gen = 0;
- for (int i = 0; i < 3; i++) jj_la1[i] = -1;
- }
-
- public void ReInit(ContentTypeParserTokenManager tm) {
- token_source = tm;
- token = new Token();
- jj_ntk = -1;
- jj_gen = 0;
- for (int i = 0; i < 3; i++) jj_la1[i] = -1;
- }
-
- final private Token jj_consume_token(int kind) throws ParseException {
- Token oldToken;
- if ((oldToken = token).next != null) token = token.next;
- else token = token.next = token_source.getNextToken();
- jj_ntk = -1;
- if (token.kind == kind) {
- jj_gen++;
- return token;
- }
- token = oldToken;
- jj_kind = kind;
- throw generateParseException();
- }
-
- final public Token getNextToken() {
- if (token.next != null) token = token.next;
- else token = token.next = token_source.getNextToken();
- jj_ntk = -1;
- jj_gen++;
- return token;
- }
-
- final public Token getToken(int index) {
- Token t = token;
- for (int i = 0; i < index; i++) {
- if (t.next != null) t = t.next;
- else t = t.next = token_source.getNextToken();
- }
- return t;
- }
-
- final private int jj_ntk() {
- if ((jj_nt=token.next) == null)
- return (jj_ntk = (token.next=token_source.getNextToken()).kind);
- else
- return (jj_ntk = jj_nt.kind);
- }
-
- private java.util.Vector jj_expentries = new java.util.Vector();
- private int[] jj_expentry;
- private int jj_kind = -1;
-
- public ParseException generateParseException() {
- jj_expentries.removeAllElements();
- boolean[] la1tokens = new boolean[24];
- for (int i = 0; i < 24; i++) {
- la1tokens[i] = false;
- }
- if (jj_kind >= 0) {
- la1tokens[jj_kind] = true;
- jj_kind = -1;
- }
- for (int i = 0; i < 3; i++) {
- if (jj_la1[i] == jj_gen) {
- for (int j = 0; j < 32; j++) {
- if ((jj_la1_0[i] & (1<<j)) != 0) {
- la1tokens[j] = true;
- }
- }
- }
- }
- for (int i = 0; i < 24; i++) {
- if (la1tokens[i]) {
- jj_expentry = new int[1];
- jj_expentry[0] = i;
- jj_expentries.addElement(jj_expentry);
- }
- }
- int[][] exptokseq = new int[jj_expentries.size()][];
- for (int i = 0; i < jj_expentries.size(); i++) {
- exptokseq[i] = (int[])jj_expentries.elementAt(i);
- }
- return new ParseException(token, exptokseq, tokenImage);
- }
-
- final public void enable_tracing() {
- }
-
- final public void disable_tracing() {
- }
-
-}
diff --git a/src/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParserConstants.java b/src/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParserConstants.java
deleted file mode 100644
index 8a763287d..000000000
--- a/src/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParserConstants.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. ContentTypeParserConstants.java */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.contenttype.parser;
-
-public interface ContentTypeParserConstants {
-
- int EOF = 0;
- int WS = 6;
- int COMMENT = 8;
- int QUOTEDSTRING = 19;
- int DIGITS = 20;
- int ATOKEN = 21;
- int QUOTEDPAIR = 22;
- int ANY = 23;
-
- int DEFAULT = 0;
- int INCOMMENT = 1;
- int NESTED_COMMENT = 2;
- int INQUOTEDSTRING = 3;
-
- String[] tokenImage = {
- "<EOF>",
- "\"\\r\"",
- "\"\\n\"",
- "\"/\"",
- "\";\"",
- "\"=\"",
- "<WS>",
- "\"(\"",
- "\")\"",
- "<token of kind 9>",
- "\"(\"",
- "<token of kind 11>",
- "<token of kind 12>",
- "\"(\"",
- "\")\"",
- "<token of kind 15>",
- "\"\\\"\"",
- "<token of kind 17>",
- "<token of kind 18>",
- "\"\\\"\"",
- "<DIGITS>",
- "<ATOKEN>",
- "<QUOTEDPAIR>",
- "<ANY>",
- };
-
-}
diff --git a/src/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParserTokenManager.java b/src/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParserTokenManager.java
deleted file mode 100644
index 05d940db5..000000000
--- a/src/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParserTokenManager.java
+++ /dev/null
@@ -1,877 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. ContentTypeParserTokenManager.java */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.contenttype.parser;
-import java.util.ArrayList;
-
-public class ContentTypeParserTokenManager implements ContentTypeParserConstants
-{
- // Keeps track of how many levels of comment nesting
- // we've encountered. This is only used when the 2nd
- // level is reached, for example ((this)), not (this).
- // This is because the outermost level must be treated
- // specially anyway, because the outermost ")" has a
- // different token type than inner ")" instances.
- static int commentNest;
- public java.io.PrintStream debugStream = System.out;
- public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
-private final int jjStopStringLiteralDfa_0(int pos, long active0)
-{
- switch (pos)
- {
- default :
- return -1;
- }
-}
-private final int jjStartNfa_0(int pos, long active0)
-{
- return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
-}
-private final int jjStopAtPos(int pos, int kind)
-{
- jjmatchedKind = kind;
- jjmatchedPos = pos;
- return pos + 1;
-}
-private final int jjStartNfaWithStates_0(int pos, int kind, int state)
-{
- jjmatchedKind = kind;
- jjmatchedPos = pos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return pos + 1; }
- return jjMoveNfa_0(state, pos + 1);
-}
-private final int jjMoveStringLiteralDfa0_0()
-{
- switch(curChar)
- {
- case 10:
- return jjStartNfaWithStates_0(0, 2, 2);
- case 13:
- return jjStartNfaWithStates_0(0, 1, 2);
- case 34:
- return jjStopAtPos(0, 16);
- case 40:
- return jjStopAtPos(0, 7);
- case 47:
- return jjStopAtPos(0, 3);
- case 59:
- return jjStopAtPos(0, 4);
- case 61:
- return jjStopAtPos(0, 5);
- default :
- return jjMoveNfa_0(3, 0);
- }
-}
-private final void jjCheckNAdd(int state)
-{
- if (jjrounds[state] != jjround)
- {
- jjstateSet[jjnewStateCnt++] = state;
- jjrounds[state] = jjround;
- }
-}
-private final void jjAddStates(int start, int end)
-{
- do {
- jjstateSet[jjnewStateCnt++] = jjnextStates[start];
- } while (start++ != end);
-}
-private final void jjCheckNAddTwoStates(int state1, int state2)
-{
- jjCheckNAdd(state1);
- jjCheckNAdd(state2);
-}
-private final void jjCheckNAddStates(int start, int end)
-{
- do {
- jjCheckNAdd(jjnextStates[start]);
- } while (start++ != end);
-}
-private final void jjCheckNAddStates(int start)
-{
- jjCheckNAdd(jjnextStates[start]);
- jjCheckNAdd(jjnextStates[start + 1]);
-}
-static final long[] jjbitVec0 = {
- 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
-};
-private final int jjMoveNfa_0(int startState, int curPos)
-{
- int[] nextStates;
- int startsAt = 0;
- jjnewStateCnt = 3;
- int i = 1;
- jjstateSet[0] = startState;
- int j, kind = 0x7fffffff;
- for (;;)
- {
- if (++jjround == 0x7fffffff)
- ReInitRounds();
- if (curChar < 64)
- {
- long l = 1L << curChar;
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 3:
- if ((0x3ff6cfafffffdffL & l) != 0L)
- {
- if (kind > 21)
- kind = 21;
- jjCheckNAdd(2);
- }
- else if ((0x100000200L & l) != 0L)
- {
- if (kind > 6)
- kind = 6;
- jjCheckNAdd(0);
- }
- if ((0x3ff000000000000L & l) != 0L)
- {
- if (kind > 20)
- kind = 20;
- jjCheckNAdd(1);
- }
- break;
- case 0:
- if ((0x100000200L & l) == 0L)
- break;
- kind = 6;
- jjCheckNAdd(0);
- break;
- case 1:
- if ((0x3ff000000000000L & l) == 0L)
- break;
- if (kind > 20)
- kind = 20;
- jjCheckNAdd(1);
- break;
- case 2:
- if ((0x3ff6cfafffffdffL & l) == 0L)
- break;
- if (kind > 21)
- kind = 21;
- jjCheckNAdd(2);
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else if (curChar < 128)
- {
- long l = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 3:
- case 2:
- if ((0xffffffffc7fffffeL & l) == 0L)
- break;
- kind = 21;
- jjCheckNAdd(2);
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else
- {
- int i2 = (curChar & 0xff) >> 6;
- long l2 = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 3:
- case 2:
- if ((jjbitVec0[i2] & l2) == 0L)
- break;
- if (kind > 21)
- kind = 21;
- jjCheckNAdd(2);
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- if (kind != 0x7fffffff)
- {
- jjmatchedKind = kind;
- jjmatchedPos = curPos;
- kind = 0x7fffffff;
- }
- ++curPos;
- if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
- return curPos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return curPos; }
- }
-}
-private final int jjStopStringLiteralDfa_1(int pos, long active0)
-{
- switch (pos)
- {
- default :
- return -1;
- }
-}
-private final int jjStartNfa_1(int pos, long active0)
-{
- return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1);
-}
-private final int jjStartNfaWithStates_1(int pos, int kind, int state)
-{
- jjmatchedKind = kind;
- jjmatchedPos = pos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return pos + 1; }
- return jjMoveNfa_1(state, pos + 1);
-}
-private final int jjMoveStringLiteralDfa0_1()
-{
- switch(curChar)
- {
- case 40:
- return jjStopAtPos(0, 10);
- case 41:
- return jjStopAtPos(0, 8);
- default :
- return jjMoveNfa_1(0, 0);
- }
-}
-private final int jjMoveNfa_1(int startState, int curPos)
-{
- int[] nextStates;
- int startsAt = 0;
- jjnewStateCnt = 3;
- int i = 1;
- jjstateSet[0] = startState;
- int j, kind = 0x7fffffff;
- for (;;)
- {
- if (++jjround == 0x7fffffff)
- ReInitRounds();
- if (curChar < 64)
- {
- long l = 1L << curChar;
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if (kind > 11)
- kind = 11;
- break;
- case 1:
- if (kind > 9)
- kind = 9;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else if (curChar < 128)
- {
- long l = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if (kind > 11)
- kind = 11;
- if (curChar == 92)
- jjstateSet[jjnewStateCnt++] = 1;
- break;
- case 1:
- if (kind > 9)
- kind = 9;
- break;
- case 2:
- if (kind > 11)
- kind = 11;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else
- {
- int i2 = (curChar & 0xff) >> 6;
- long l2 = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if ((jjbitVec0[i2] & l2) != 0L && kind > 11)
- kind = 11;
- break;
- case 1:
- if ((jjbitVec0[i2] & l2) != 0L && kind > 9)
- kind = 9;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- if (kind != 0x7fffffff)
- {
- jjmatchedKind = kind;
- jjmatchedPos = curPos;
- kind = 0x7fffffff;
- }
- ++curPos;
- if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
- return curPos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return curPos; }
- }
-}
-private final int jjStopStringLiteralDfa_3(int pos, long active0)
-{
- switch (pos)
- {
- default :
- return -1;
- }
-}
-private final int jjStartNfa_3(int pos, long active0)
-{
- return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0), pos + 1);
-}
-private final int jjStartNfaWithStates_3(int pos, int kind, int state)
-{
- jjmatchedKind = kind;
- jjmatchedPos = pos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return pos + 1; }
- return jjMoveNfa_3(state, pos + 1);
-}
-private final int jjMoveStringLiteralDfa0_3()
-{
- switch(curChar)
- {
- case 34:
- return jjStopAtPos(0, 19);
- default :
- return jjMoveNfa_3(0, 0);
- }
-}
-private final int jjMoveNfa_3(int startState, int curPos)
-{
- int[] nextStates;
- int startsAt = 0;
- jjnewStateCnt = 3;
- int i = 1;
- jjstateSet[0] = startState;
- int j, kind = 0x7fffffff;
- for (;;)
- {
- if (++jjround == 0x7fffffff)
- ReInitRounds();
- if (curChar < 64)
- {
- long l = 1L << curChar;
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- case 2:
- if ((0xfffffffbffffffffL & l) == 0L)
- break;
- if (kind > 18)
- kind = 18;
- jjCheckNAdd(2);
- break;
- case 1:
- if (kind > 17)
- kind = 17;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else if (curChar < 128)
- {
- long l = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if ((0xffffffffefffffffL & l) != 0L)
- {
- if (kind > 18)
- kind = 18;
- jjCheckNAdd(2);
- }
- else if (curChar == 92)
- jjstateSet[jjnewStateCnt++] = 1;
- break;
- case 1:
- if (kind > 17)
- kind = 17;
- break;
- case 2:
- if ((0xffffffffefffffffL & l) == 0L)
- break;
- if (kind > 18)
- kind = 18;
- jjCheckNAdd(2);
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else
- {
- int i2 = (curChar & 0xff) >> 6;
- long l2 = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- case 2:
- if ((jjbitVec0[i2] & l2) == 0L)
- break;
- if (kind > 18)
- kind = 18;
- jjCheckNAdd(2);
- break;
- case 1:
- if ((jjbitVec0[i2] & l2) != 0L && kind > 17)
- kind = 17;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- if (kind != 0x7fffffff)
- {
- jjmatchedKind = kind;
- jjmatchedPos = curPos;
- kind = 0x7fffffff;
- }
- ++curPos;
- if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
- return curPos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return curPos; }
- }
-}
-private final int jjStopStringLiteralDfa_2(int pos, long active0)
-{
- switch (pos)
- {
- default :
- return -1;
- }
-}
-private final int jjStartNfa_2(int pos, long active0)
-{
- return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1);
-}
-private final int jjStartNfaWithStates_2(int pos, int kind, int state)
-{
- jjmatchedKind = kind;
- jjmatchedPos = pos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return pos + 1; }
- return jjMoveNfa_2(state, pos + 1);
-}
-private final int jjMoveStringLiteralDfa0_2()
-{
- switch(curChar)
- {
- case 40:
- return jjStopAtPos(0, 13);
- case 41:
- return jjStopAtPos(0, 14);
- default :
- return jjMoveNfa_2(0, 0);
- }
-}
-private final int jjMoveNfa_2(int startState, int curPos)
-{
- int[] nextStates;
- int startsAt = 0;
- jjnewStateCnt = 3;
- int i = 1;
- jjstateSet[0] = startState;
- int j, kind = 0x7fffffff;
- for (;;)
- {
- if (++jjround == 0x7fffffff)
- ReInitRounds();
- if (curChar < 64)
- {
- long l = 1L << curChar;
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if (kind > 15)
- kind = 15;
- break;
- case 1:
- if (kind > 12)
- kind = 12;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else if (curChar < 128)
- {
- long l = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if (kind > 15)
- kind = 15;
- if (curChar == 92)
- jjstateSet[jjnewStateCnt++] = 1;
- break;
- case 1:
- if (kind > 12)
- kind = 12;
- break;
- case 2:
- if (kind > 15)
- kind = 15;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else
- {
- int i2 = (curChar & 0xff) >> 6;
- long l2 = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if ((jjbitVec0[i2] & l2) != 0L && kind > 15)
- kind = 15;
- break;
- case 1:
- if ((jjbitVec0[i2] & l2) != 0L && kind > 12)
- kind = 12;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- if (kind != 0x7fffffff)
- {
- jjmatchedKind = kind;
- jjmatchedPos = curPos;
- kind = 0x7fffffff;
- }
- ++curPos;
- if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
- return curPos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return curPos; }
- }
-}
-static final int[] jjnextStates = {
-};
-public static final String[] jjstrLiteralImages = {
-"", "\15", "\12", "\57", "\73", "\75", null, null, null, null, null, null,
-null, null, null, null, null, null, null, null, null, null, null, null, };
-public static final String[] lexStateNames = {
- "DEFAULT",
- "INCOMMENT",
- "NESTED_COMMENT",
- "INQUOTEDSTRING",
-};
-public static final int[] jjnewLexState = {
- -1, -1, -1, -1, -1, -1, -1, 1, 0, -1, 2, -1, -1, -1, -1, -1, 3, -1, -1, 0, -1, -1, -1, -1,
-};
-static final long[] jjtoToken = {
- 0x38003fL,
-};
-static final long[] jjtoSkip = {
- 0x140L,
-};
-static final long[] jjtoSpecial = {
- 0x40L,
-};
-static final long[] jjtoMore = {
- 0x7fe80L,
-};
-protected SimpleCharStream input_stream;
-private final int[] jjrounds = new int[3];
-private final int[] jjstateSet = new int[6];
-StringBuffer image;
-int jjimageLen;
-int lengthOfMatch;
-protected char curChar;
-public ContentTypeParserTokenManager(SimpleCharStream stream){
- if (SimpleCharStream.staticFlag)
- throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
- input_stream = stream;
-}
-public ContentTypeParserTokenManager(SimpleCharStream stream, int lexState){
- this(stream);
- SwitchTo(lexState);
-}
-public void ReInit(SimpleCharStream stream)
-{
- jjmatchedPos = jjnewStateCnt = 0;
- curLexState = defaultLexState;
- input_stream = stream;
- ReInitRounds();
-}
-private final void ReInitRounds()
-{
- int i;
- jjround = 0x80000001;
- for (i = 3; i-- > 0;)
- jjrounds[i] = 0x80000000;
-}
-public void ReInit(SimpleCharStream stream, int lexState)
-{
- ReInit(stream);
- SwitchTo(lexState);
-}
-public void SwitchTo(int lexState)
-{
- if (lexState >= 4 || lexState < 0)
- throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
- else
- curLexState = lexState;
-}
-
-protected Token jjFillToken()
-{
- Token t = Token.newToken(jjmatchedKind);
- t.kind = jjmatchedKind;
- String im = jjstrLiteralImages[jjmatchedKind];
- t.image = (im == null) ? input_stream.GetImage() : im;
- t.beginLine = input_stream.getBeginLine();
- t.beginColumn = input_stream.getBeginColumn();
- t.endLine = input_stream.getEndLine();
- t.endColumn = input_stream.getEndColumn();
- return t;
-}
-
-int curLexState = 0;
-int defaultLexState = 0;
-int jjnewStateCnt;
-int jjround;
-int jjmatchedPos;
-int jjmatchedKind;
-
-public Token getNextToken()
-{
- int kind;
- Token specialToken = null;
- Token matchedToken;
- int curPos = 0;
-
- EOFLoop :
- for (;;)
- {
- try
- {
- curChar = input_stream.BeginToken();
- }
- catch(java.io.IOException e)
- {
- jjmatchedKind = 0;
- matchedToken = jjFillToken();
- matchedToken.specialToken = specialToken;
- return matchedToken;
- }
- image = null;
- jjimageLen = 0;
-
- for (;;)
- {
- switch(curLexState)
- {
- case 0:
- jjmatchedKind = 0x7fffffff;
- jjmatchedPos = 0;
- curPos = jjMoveStringLiteralDfa0_0();
- break;
- case 1:
- jjmatchedKind = 0x7fffffff;
- jjmatchedPos = 0;
- curPos = jjMoveStringLiteralDfa0_1();
- break;
- case 2:
- jjmatchedKind = 0x7fffffff;
- jjmatchedPos = 0;
- curPos = jjMoveStringLiteralDfa0_2();
- break;
- case 3:
- jjmatchedKind = 0x7fffffff;
- jjmatchedPos = 0;
- curPos = jjMoveStringLiteralDfa0_3();
- break;
- }
- if (jjmatchedKind != 0x7fffffff)
- {
- if (jjmatchedPos + 1 < curPos)
- input_stream.backup(curPos - jjmatchedPos - 1);
- if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
- {
- matchedToken = jjFillToken();
- matchedToken.specialToken = specialToken;
- TokenLexicalActions(matchedToken);
- if (jjnewLexState[jjmatchedKind] != -1)
- curLexState = jjnewLexState[jjmatchedKind];
- return matchedToken;
- }
- else if ((jjtoSkip[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
- {
- if ((jjtoSpecial[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
- {
- matchedToken = jjFillToken();
- if (specialToken == null)
- specialToken = matchedToken;
- else
- {
- matchedToken.specialToken = specialToken;
- specialToken = (specialToken.next = matchedToken);
- }
- }
- if (jjnewLexState[jjmatchedKind] != -1)
- curLexState = jjnewLexState[jjmatchedKind];
- continue EOFLoop;
- }
- MoreLexicalActions();
- if (jjnewLexState[jjmatchedKind] != -1)
- curLexState = jjnewLexState[jjmatchedKind];
- curPos = 0;
- jjmatchedKind = 0x7fffffff;
- try {
- curChar = input_stream.readChar();
- continue;
- }
- catch (java.io.IOException e1) { }
- }
- int error_line = input_stream.getEndLine();
- int error_column = input_stream.getEndColumn();
- String error_after = null;
- boolean EOFSeen = false;
- try { input_stream.readChar(); input_stream.backup(1); }
- catch (java.io.IOException e1) {
- EOFSeen = true;
- error_after = curPos <= 1 ? "" : input_stream.GetImage();
- if (curChar == '\n' || curChar == '\r') {
- error_line++;
- error_column = 0;
- }
- else
- error_column++;
- }
- if (!EOFSeen) {
- input_stream.backup(1);
- error_after = curPos <= 1 ? "" : input_stream.GetImage();
- }
- throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
- }
- }
-}
-
-void MoreLexicalActions()
-{
- jjimageLen += (lengthOfMatch = jjmatchedPos + 1);
- switch(jjmatchedKind)
- {
- case 9 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- image.deleteCharAt(image.length() - 2);
- break;
- case 10 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- commentNest = 1;
- break;
- case 12 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- image.deleteCharAt(image.length() - 2);
- break;
- case 13 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- ++commentNest;
- break;
- case 14 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- --commentNest; if (commentNest == 0) SwitchTo(INCOMMENT);
- break;
- case 16 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- image.deleteCharAt(image.length() - 1);
- break;
- case 17 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- image.deleteCharAt(image.length() - 2);
- break;
- default :
- break;
- }
-}
-void TokenLexicalActions(Token matchedToken)
-{
- switch(jjmatchedKind)
- {
- case 19 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
- matchedToken.image = image.substring(0, image.length() - 1);
- break;
- default :
- break;
- }
-}
-}
diff --git a/src/org/apache/james/mime4j/field/contenttype/parser/ParseException.java b/src/org/apache/james/mime4j/field/contenttype/parser/ParseException.java
deleted file mode 100644
index 2c5dc8275..000000000
--- a/src/org/apache/james/mime4j/field/contenttype/parser/ParseException.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.contenttype.parser;
-
-/**
- * This exception is thrown when parse errors are encountered.
- * You can explicitly create objects of this exception type by
- * calling the method generateParseException in the generated
- * parser.
- *
- * You can modify this class to customize your error reporting
- * mechanisms so long as you retain the public fields.
- */
-public class ParseException extends Exception {
-
- /**
- * This constructor is used by the method "generateParseException"
- * in the generated parser. Calling this constructor generates
- * a new object of this type with the fields "currentToken",
- * "expectedTokenSequences", and "tokenImage" set. The boolean
- * flag "specialConstructor" is also set to true to indicate that
- * this constructor was used to create this object.
- * This constructor calls its super class with the empty string
- * to force the "toString" method of parent class "Throwable" to
- * print the error message in the form:
- * ParseException: <result of getMessage>
- */
- public ParseException(Token currentTokenVal,
- int[][] expectedTokenSequencesVal,
- String[] tokenImageVal
- )
- {
- super("");
- specialConstructor = true;
- currentToken = currentTokenVal;
- expectedTokenSequences = expectedTokenSequencesVal;
- tokenImage = tokenImageVal;
- }
-
- /**
- * The following constructors are for use by you for whatever
- * purpose you can think of. Constructing the exception in this
- * manner makes the exception behave in the normal way - i.e., as
- * documented in the class "Throwable". The fields "errorToken",
- * "expectedTokenSequences", and "tokenImage" do not contain
- * relevant information. The JavaCC generated code does not use
- * these constructors.
- */
-
- public ParseException() {
- super();
- specialConstructor = false;
- }
-
- public ParseException(String message) {
- super(message);
- specialConstructor = false;
- }
-
- /**
- * This variable determines which constructor was used to create
- * this object and thereby affects the semantics of the
- * "getMessage" method (see below).
- */
- protected boolean specialConstructor;
-
- /**
- * This is the last token that has been consumed successfully. If
- * this object has been created due to a parse error, the token
- * followng this token will (therefore) be the first error token.
- */
- public Token currentToken;
-
- /**
- * Each entry in this array is an array of integers. Each array
- * of integers represents a sequence of tokens (by their ordinal
- * values) that is expected at this point of the parse.
- */
- public int[][] expectedTokenSequences;
-
- /**
- * This is a reference to the "tokenImage" array of the generated
- * parser within which the parse error occurred. This array is
- * defined in the generated ...Constants interface.
- */
- public String[] tokenImage;
-
- /**
- * This method has the standard behavior when this object has been
- * created using the standard constructors. Otherwise, it uses
- * "currentToken" and "expectedTokenSequences" to generate a parse
- * error message and returns it. If this object has been created
- * due to a parse error, and you do not catch it (it gets thrown
- * from the parser), then this method is called during the printing
- * of the final stack trace, and hence the correct error message
- * gets displayed.
- */
- public String getMessage() {
- if (!specialConstructor) {
- return super.getMessage();
- }
- StringBuffer expected = new StringBuffer();
- int maxSize = 0;
- for (int i = 0; i < expectedTokenSequences.length; i++) {
- if (maxSize < expectedTokenSequences[i].length) {
- maxSize = expectedTokenSequences[i].length;
- }
- for (int j = 0; j < expectedTokenSequences[i].length; j++) {
- expected.append(tokenImage[expectedTokenSequences[i][j]]).append(" ");
- }
- if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
- expected.append("...");
- }
- expected.append(eol).append(" ");
- }
- String retval = "Encountered \"";
- Token tok = currentToken.next;
- for (int i = 0; i < maxSize; i++) {
- if (i != 0) retval += " ";
- if (tok.kind == 0) {
- retval += tokenImage[0];
- break;
- }
- retval += add_escapes(tok.image);
- tok = tok.next;
- }
- retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
- retval += "." + eol;
- if (expectedTokenSequences.length == 1) {
- retval += "Was expecting:" + eol + " ";
- } else {
- retval += "Was expecting one of:" + eol + " ";
- }
- retval += expected.toString();
- return retval;
- }
-
- /**
- * The end of line string for this machine.
- */
- protected String eol = System.getProperty("line.separator", "\n");
-
- /**
- * Used to convert raw characters to their escaped version
- * when these raw version cannot be used as part of an ASCII
- * string literal.
- */
- protected String add_escapes(String str) {
- StringBuffer retval = new StringBuffer();
- char ch;
- for (int i = 0; i < str.length(); i++) {
- switch (str.charAt(i))
- {
- case 0 :
- continue;
- case '\b':
- retval.append("\\b");
- continue;
- case '\t':
- retval.append("\\t");
- continue;
- case '\n':
- retval.append("\\n");
- continue;
- case '\f':
- retval.append("\\f");
- continue;
- case '\r':
- retval.append("\\r");
- continue;
- case '\"':
- retval.append("\\\"");
- continue;
- case '\'':
- retval.append("\\\'");
- continue;
- case '\\':
- retval.append("\\\\");
- continue;
- default:
- if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
- String s = "0000" + Integer.toString(ch, 16);
- retval.append("\\u" + s.substring(s.length() - 4, s.length()));
- } else {
- retval.append(ch);
- }
- continue;
- }
- }
- return retval.toString();
- }
-
-}
diff --git a/src/org/apache/james/mime4j/field/contenttype/parser/SimpleCharStream.java b/src/org/apache/james/mime4j/field/contenttype/parser/SimpleCharStream.java
deleted file mode 100644
index c139e4f38..000000000
--- a/src/org/apache/james/mime4j/field/contenttype/parser/SimpleCharStream.java
+++ /dev/null
@@ -1,454 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.0 */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.contenttype.parser;
-
-/**
- * An implementation of interface CharStream, where the stream is assumed to
- * contain only ASCII characters (without unicode processing).
- */
-
-public class SimpleCharStream
-{
- public static final boolean staticFlag = false;
- int bufsize;
- int available;
- int tokenBegin;
- public int bufpos = -1;
- protected int bufline[];
- protected int bufcolumn[];
-
- protected int column = 0;
- protected int line = 1;
-
- protected boolean prevCharIsCR = false;
- protected boolean prevCharIsLF = false;
-
- protected java.io.Reader inputStream;
-
- protected char[] buffer;
- protected int maxNextCharInd = 0;
- protected int inBuf = 0;
- protected int tabSize = 8;
-
- protected void setTabSize(int i) { tabSize = i; }
- protected int getTabSize(int i) { return tabSize; }
-
-
- protected void ExpandBuff(boolean wrapAround)
- {
- char[] newbuffer = new char[bufsize + 2048];
- int newbufline[] = new int[bufsize + 2048];
- int newbufcolumn[] = new int[bufsize + 2048];
-
- try
- {
- if (wrapAround)
- {
- System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
- System.arraycopy(buffer, 0, newbuffer,
- bufsize - tokenBegin, bufpos);
- buffer = newbuffer;
-
- System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
- System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
- bufline = newbufline;
-
- System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
- System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
- bufcolumn = newbufcolumn;
-
- maxNextCharInd = (bufpos += (bufsize - tokenBegin));
- }
- else
- {
- System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
- buffer = newbuffer;
-
- System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
- bufline = newbufline;
-
- System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
- bufcolumn = newbufcolumn;
-
- maxNextCharInd = (bufpos -= tokenBegin);
- }
- }
- catch (Throwable t)
- {
- throw new Error(t.getMessage());
- }
-
-
- bufsize += 2048;
- available = bufsize;
- tokenBegin = 0;
- }
-
- protected void FillBuff() throws java.io.IOException
- {
- if (maxNextCharInd == available)
- {
- if (available == bufsize)
- {
- if (tokenBegin > 2048)
- {
- bufpos = maxNextCharInd = 0;
- available = tokenBegin;
- }
- else if (tokenBegin < 0)
- bufpos = maxNextCharInd = 0;
- else
- ExpandBuff(false);
- }
- else if (available > tokenBegin)
- available = bufsize;
- else if ((tokenBegin - available) < 2048)
- ExpandBuff(true);
- else
- available = tokenBegin;
- }
-
- int i;
- try {
- if ((i = inputStream.read(buffer, maxNextCharInd,
- available - maxNextCharInd)) == -1)
- {
- inputStream.close();
- throw new java.io.IOException();
- }
- else
- maxNextCharInd += i;
- return;
- }
- catch(java.io.IOException e) {
- --bufpos;
- backup(0);
- if (tokenBegin == -1)
- tokenBegin = bufpos;
- throw e;
- }
- }
-
- public char BeginToken() throws java.io.IOException
- {
- tokenBegin = -1;
- char c = readChar();
- tokenBegin = bufpos;
-
- return c;
- }
-
- protected void UpdateLineColumn(char c)
- {
- column++;
-
- if (prevCharIsLF)
- {
- prevCharIsLF = false;
- line += (column = 1);
- }
- else if (prevCharIsCR)
- {
- prevCharIsCR = false;
- if (c == '\n')
- {
- prevCharIsLF = true;
- }
- else
- line += (column = 1);
- }
-
- switch (c)
- {
- case '\r' :
- prevCharIsCR = true;
- break;
- case '\n' :
- prevCharIsLF = true;
- break;
- case '\t' :
- column--;
- column += (tabSize - (column % tabSize));
- break;
- default :
- break;
- }
-
- bufline[bufpos] = line;
- bufcolumn[bufpos] = column;
- }
-
- public char readChar() throws java.io.IOException
- {
- if (inBuf > 0)
- {
- --inBuf;
-
- if (++bufpos == bufsize)
- bufpos = 0;
-
- return buffer[bufpos];
- }
-
- if (++bufpos >= maxNextCharInd)
- FillBuff();
-
- char c = buffer[bufpos];
-
- UpdateLineColumn(c);
- return (c);
- }
-
- /**
- * @deprecated
- * @see #getEndColumn
- */
-
- public int getColumn() {
- return bufcolumn[bufpos];
- }
-
- /**
- * @deprecated
- * @see #getEndLine
- */
-
- public int getLine() {
- return bufline[bufpos];
- }
-
- public int getEndColumn() {
- return bufcolumn[bufpos];
- }
-
- public int getEndLine() {
- return bufline[bufpos];
- }
-
- public int getBeginColumn() {
- return bufcolumn[tokenBegin];
- }
-
- public int getBeginLine() {
- return bufline[tokenBegin];
- }
-
- public void backup(int amount) {
-
- inBuf += amount;
- if ((bufpos -= amount) < 0)
- bufpos += bufsize;
- }
-
- public SimpleCharStream(java.io.Reader dstream, int startline,
- int startcolumn, int buffersize)
- {
- inputStream = dstream;
- line = startline;
- column = startcolumn - 1;
-
- available = bufsize = buffersize;
- buffer = new char[buffersize];
- bufline = new int[buffersize];
- bufcolumn = new int[buffersize];
- }
-
- public SimpleCharStream(java.io.Reader dstream, int startline,
- int startcolumn)
- {
- this(dstream, startline, startcolumn, 4096);
- }
-
- public SimpleCharStream(java.io.Reader dstream)
- {
- this(dstream, 1, 1, 4096);
- }
- public void ReInit(java.io.Reader dstream, int startline,
- int startcolumn, int buffersize)
- {
- inputStream = dstream;
- line = startline;
- column = startcolumn - 1;
-
- if (buffer == null || buffersize != buffer.length)
- {
- available = bufsize = buffersize;
- buffer = new char[buffersize];
- bufline = new int[buffersize];
- bufcolumn = new int[buffersize];
- }
- prevCharIsLF = prevCharIsCR = false;
- tokenBegin = inBuf = maxNextCharInd = 0;
- bufpos = -1;
- }
-
- public void ReInit(java.io.Reader dstream, int startline,
- int startcolumn)
- {
- ReInit(dstream, startline, startcolumn, 4096);
- }
-
- public void ReInit(java.io.Reader dstream)
- {
- ReInit(dstream, 1, 1, 4096);
- }
- public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
- int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
- {
- this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
- }
-
- public SimpleCharStream(java.io.InputStream dstream, int startline,
- int startcolumn, int buffersize)
- {
- this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
- }
-
- public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
- int startcolumn) throws java.io.UnsupportedEncodingException
- {
- this(dstream, encoding, startline, startcolumn, 4096);
- }
-
- public SimpleCharStream(java.io.InputStream dstream, int startline,
- int startcolumn)
- {
- this(dstream, startline, startcolumn, 4096);
- }
-
- public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
- {
- this(dstream, encoding, 1, 1, 4096);
- }
-
- public SimpleCharStream(java.io.InputStream dstream)
- {
- this(dstream, 1, 1, 4096);
- }
-
- public void ReInit(java.io.InputStream dstream, String encoding, int startline,
- int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
- {
- ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
- }
-
- public void ReInit(java.io.InputStream dstream, int startline,
- int startcolumn, int buffersize)
- {
- ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
- }
-
- public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
- {
- ReInit(dstream, encoding, 1, 1, 4096);
- }
-
- public void ReInit(java.io.InputStream dstream)
- {
- ReInit(dstream, 1, 1, 4096);
- }
- public void ReInit(java.io.InputStream dstream, String encoding, int startline,
- int startcolumn) throws java.io.UnsupportedEncodingException
- {
- ReInit(dstream, encoding, startline, startcolumn, 4096);
- }
- public void ReInit(java.io.InputStream dstream, int startline,
- int startcolumn)
- {
- ReInit(dstream, startline, startcolumn, 4096);
- }
- public String GetImage()
- {
- if (bufpos >= tokenBegin)
- return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
- else
- return new String(buffer, tokenBegin, bufsize - tokenBegin) +
- new String(buffer, 0, bufpos + 1);
- }
-
- public char[] GetSuffix(int len)
- {
- char[] ret = new char[len];
-
- if ((bufpos + 1) >= len)
- System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
- else
- {
- System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
- len - bufpos - 1);
- System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
- }
-
- return ret;
- }
-
- public void Done()
- {
- buffer = null;
- bufline = null;
- bufcolumn = null;
- }
-
- /**
- * Method to adjust line and column numbers for the start of a token.
- */
- public void adjustBeginLineColumn(int newLine, int newCol)
- {
- int start = tokenBegin;
- int len;
-
- if (bufpos >= tokenBegin)
- {
- len = bufpos - tokenBegin + inBuf + 1;
- }
- else
- {
- len = bufsize - tokenBegin + bufpos + 1 + inBuf;
- }
-
- int i = 0, j = 0, k = 0;
- int nextColDiff = 0, columnDiff = 0;
-
- while (i < len &&
- bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
- {
- bufline[j] = newLine;
- nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
- bufcolumn[j] = newCol + columnDiff;
- columnDiff = nextColDiff;
- i++;
- }
-
- if (i < len)
- {
- bufline[j] = newLine++;
- bufcolumn[j] = newCol + columnDiff;
-
- while (i++ < len)
- {
- if (bufline[j = start % bufsize] != bufline[++start % bufsize])
- bufline[j] = newLine++;
- else
- bufline[j] = newLine;
- }
- }
-
- line = bufline[j];
- column = bufcolumn[j];
- }
-
-}
diff --git a/src/org/apache/james/mime4j/field/contenttype/parser/Token.java b/src/org/apache/james/mime4j/field/contenttype/parser/Token.java
deleted file mode 100644
index 5bef6cf02..000000000
--- a/src/org/apache/james/mime4j/field/contenttype/parser/Token.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.contenttype.parser;
-
-/**
- * Describes the input token stream.
- */
-
-public class Token {
-
- /**
- * An integer that describes the kind of this token. This numbering
- * system is determined by JavaCCParser, and a table of these numbers is
- * stored in the file ...Constants.java.
- */
- public int kind;
-
- /**
- * beginLine and beginColumn describe the position of the first character
- * of this token; endLine and endColumn describe the position of the
- * last character of this token.
- */
- public int beginLine, beginColumn, endLine, endColumn;
-
- /**
- * The string image of the token.
- */
- public String image;
-
- /**
- * A reference to the next regular (non-special) token from the input
- * stream. If this is the last token from the input stream, or if the
- * token manager has not read tokens beyond this one, this field is
- * set to null. This is true only if this token is also a regular
- * token. Otherwise, see below for a description of the contents of
- * this field.
- */
- public Token next;
-
- /**
- * This field is used to access special tokens that occur prior to this
- * token, but after the immediately preceding regular (non-special) token.
- * If there are no such special tokens, this field is set to null.
- * When there are more than one such special token, this field refers
- * to the last of these special tokens, which in turn refers to the next
- * previous special token through its specialToken field, and so on
- * until the first special token (whose specialToken field is null).
- * The next fields of special tokens refer to other special tokens that
- * immediately follow it (without an intervening regular token). If there
- * is no such token, this field is null.
- */
- public Token specialToken;
-
- /**
- * Returns the image.
- */
- public String toString()
- {
- return image;
- }
-
- /**
- * Returns a new Token object, by default. However, if you want, you
- * can create and return subclass objects based on the value of ofKind.
- * Simply add the cases to the switch for all those special cases.
- * For example, if you have a subclass of Token called IDToken that
- * you want to create if ofKind is ID, simlpy add something like :
- *
- * case MyParserConstants.ID : return new IDToken();
- *
- * to the following switch statement. Then you can cast matchedToken
- * variable to the appropriate type and use it in your lexical actions.
- */
- public static final Token newToken(int ofKind)
- {
- switch(ofKind)
- {
- default : return new Token();
- }
- }
-
-}
diff --git a/src/org/apache/james/mime4j/field/contenttype/parser/TokenMgrError.java b/src/org/apache/james/mime4j/field/contenttype/parser/TokenMgrError.java
deleted file mode 100644
index 4a490efac..000000000
--- a/src/org/apache/james/mime4j/field/contenttype/parser/TokenMgrError.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.contenttype.parser;
-
-public class TokenMgrError extends Error
-{
- /*
- * Ordinals for various reasons why an Error of this type can be thrown.
- */
-
- /**
- * Lexical error occured.
- */
- static final int LEXICAL_ERROR = 0;
-
- /**
- * An attempt wass made to create a second instance of a static token manager.
- */
- static final int STATIC_LEXER_ERROR = 1;
-
- /**
- * Tried to change to an invalid lexical state.
- */
- static final int INVALID_LEXICAL_STATE = 2;
-
- /**
- * Detected (and bailed out of) an infinite loop in the token manager.
- */
- static final int LOOP_DETECTED = 3;
-
- /**
- * Indicates the reason why the exception is thrown. It will have
- * one of the above 4 values.
- */
- int errorCode;
-
- /**
- * Replaces unprintable characters by their espaced (or unicode escaped)
- * equivalents in the given string
- */
- protected static final String addEscapes(String str) {
- StringBuffer retval = new StringBuffer();
- char ch;
- for (int i = 0; i < str.length(); i++) {
- switch (str.charAt(i))
- {
- case 0 :
- continue;
- case '\b':
- retval.append("\\b");
- continue;
- case '\t':
- retval.append("\\t");
- continue;
- case '\n':
- retval.append("\\n");
- continue;
- case '\f':
- retval.append("\\f");
- continue;
- case '\r':
- retval.append("\\r");
- continue;
- case '\"':
- retval.append("\\\"");
- continue;
- case '\'':
- retval.append("\\\'");
- continue;
- case '\\':
- retval.append("\\\\");
- continue;
- default:
- if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
- String s = "0000" + Integer.toString(ch, 16);
- retval.append("\\u" + s.substring(s.length() - 4, s.length()));
- } else {
- retval.append(ch);
- }
- continue;
- }
- }
- return retval.toString();
- }
-
- /**
- * Returns a detailed message for the Error when it is thrown by the
- * token manager to indicate a lexical error.
- * Parameters :
- * EOFSeen : indicates if EOF caused the lexicl error
- * curLexState : lexical state in which this error occured
- * errorLine : line number when the error occured
- * errorColumn : column number when the error occured
- * errorAfter : prefix that was seen before this error occured
- * curchar : the offending character
- * Note: You can customize the lexical error message by modifying this method.
- */
- protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
- return("Lexical error at line " +
- errorLine + ", column " +
- errorColumn + ". Encountered: " +
- (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
- "after : \"" + addEscapes(errorAfter) + "\"");
- }
-
- /**
- * You can also modify the body of this method to customize your error messages.
- * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
- * of end-users concern, so you can return something like :
- *
- * "Internal Error : Please file a bug report .... "
- *
- * from this method for such cases in the release version of your parser.
- */
- public String getMessage() {
- return super.getMessage();
- }
-
- /*
- * Constructors of various flavors follow.
- */
-
- public TokenMgrError() {
- }
-
- public TokenMgrError(String message, int reason) {
- super(message);
- errorCode = reason;
- }
-
- public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
- this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
- }
-}
diff --git a/src/org/apache/james/mime4j/field/datetime/DateTime.java b/src/org/apache/james/mime4j/field/datetime/DateTime.java
deleted file mode 100644
index bf00ca753..000000000
--- a/src/org/apache/james/mime4j/field/datetime/DateTime.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.field.datetime;
-
-import org.apache.james.mime4j.field.datetime.parser.DateTimeParser;
-import org.apache.james.mime4j.field.datetime.parser.ParseException;
-import org.apache.james.mime4j.field.datetime.parser.TokenMgrError;
-
-import java.util.Date;
-import java.util.Calendar;
-import java.util.TimeZone;
-import java.util.GregorianCalendar;
-import java.io.StringReader;
-
-public class DateTime {
- private final Date date;
- private final int year;
- private final int month;
- private final int day;
- private final int hour;
- private final int minute;
- private final int second;
- private final int timeZone;
-
- public DateTime(String yearString, int month, int day, int hour, int minute, int second, int timeZone) {
- this.year = convertToYear(yearString);
- this.date = convertToDate(year, month, day, hour, minute, second, timeZone);
- this.month = month;
- this.day = day;
- this.hour = hour;
- this.minute = minute;
- this.second = second;
- this.timeZone = timeZone;
- }
-
- private int convertToYear(String yearString) {
- int year = Integer.parseInt(yearString);
- switch (yearString.length()) {
- case 1:
- case 2:
- if (year >= 0 && year < 50)
- return 2000 + year;
- else
- return 1900 + year;
- case 3:
- return 1900 + year;
- default:
- return year;
- }
- }
-
- public static Date convertToDate(int year, int month, int day, int hour, int minute, int second, int timeZone) {
- Calendar c = new GregorianCalendar(TimeZone.getTimeZone("GMT+0"));
- c.set(year, month - 1, day, hour, minute, second);
- c.set(Calendar.MILLISECOND, 0);
-
- if (timeZone != Integer.MIN_VALUE) {
- int minutes = ((timeZone / 100) * 60) + timeZone % 100;
- c.add(Calendar.MINUTE, -1 * minutes);
- }
-
- return c.getTime();
- }
-
- public Date getDate() {
- return date;
- }
-
- public int getYear() {
- return year;
- }
-
- public int getMonth() {
- return month;
- }
-
- public int getDay() {
- return day;
- }
-
- public int getHour() {
- return hour;
- }
-
- public int getMinute() {
- return minute;
- }
-
- public int getSecond() {
- return second;
- }
-
- public int getTimeZone() {
- return timeZone;
- }
-
- public void print() {
- System.out.println(getYear() + " " + getMonth() + " " + getDay() + "; " + getHour() + " " + getMinute() + " " + getSecond() + " " + getTimeZone());
- }
-
-
- public static DateTime parse(String dateString) throws ParseException {
- try {
- return new DateTimeParser(new StringReader(dateString)).parseAll();
- }
- catch (TokenMgrError err) {
- throw new ParseException(err.getMessage());
- }
- }
-}
diff --git a/src/org/apache/james/mime4j/field/datetime/parser/DateTimeParser.java b/src/org/apache/james/mime4j/field/datetime/parser/DateTimeParser.java
deleted file mode 100644
index 94b517208..000000000
--- a/src/org/apache/james/mime4j/field/datetime/parser/DateTimeParser.java
+++ /dev/null
@@ -1,570 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. DateTimeParser.java */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.datetime.parser;
-
-import org.apache.james.mime4j.field.datetime.DateTime;
-
-import java.util.Calendar;
-
-public class DateTimeParser implements DateTimeParserConstants {
- private static final boolean ignoreMilitaryZoneOffset = true;
-
- public static void main(String args[]) throws ParseException {
- while (true) {
- try {
- DateTimeParser parser = new DateTimeParser(System.in);
- parser.parseLine();
- } catch (Exception x) {
- x.printStackTrace();
- return;
- }
- }
- }
-
- private static int parseDigits(Token token) {
- return Integer.parseInt(token.image, 10);
- }
-
- private static int getMilitaryZoneOffset(char c) {
- if (ignoreMilitaryZoneOffset)
- return 0;
-
- c = Character.toUpperCase(c);
-
- switch (c) {
- case 'A': return 1;
- case 'B': return 2;
- case 'C': return 3;
- case 'D': return 4;
- case 'E': return 5;
- case 'F': return 6;
- case 'G': return 7;
- case 'H': return 8;
- case 'I': return 9;
- case 'K': return 10;
- case 'L': return 11;
- case 'M': return 12;
-
- case 'N': return -1;
- case 'O': return -2;
- case 'P': return -3;
- case 'Q': return -4;
- case 'R': return -5;
- case 'S': return -6;
- case 'T': return -7;
- case 'U': return -8;
- case 'V': return -9;
- case 'W': return -10;
- case 'X': return -11;
- case 'Y': return -12;
-
- case 'Z': return 0;
- default: return 0;
- }
- }
-
- private static class Time {
- private int hour;
- private int minute;
- private int second;
- private int zone;
-
- public Time(int hour, int minute, int second, int zone) {
- this.hour = hour;
- this.minute = minute;
- this.second = second;
- this.zone = zone;
- }
-
- public int getHour() { return hour; }
- public int getMinute() { return minute; }
- public int getSecond() { return second; }
- public int getZone() { return zone; }
- }
-
- private static class Date {
- private String year;
- private int month;
- private int day;
-
- public Date(String year, int month, int day) {
- this.year = year;
- this.month = month;
- this.day = day;
- }
-
- public String getYear() { return year; }
- public int getMonth() { return month; }
- public int getDay() { return day; }
- }
-
- final public DateTime parseLine() throws ParseException {
- DateTime dt;
- dt = date_time();
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 1:
- jj_consume_token(1);
- break;
- default:
- jj_la1[0] = jj_gen;
- ;
- }
- jj_consume_token(2);
- {if (true) return dt;}
- throw new Error("Missing return statement in function");
- }
-
- final public DateTime parseAll() throws ParseException {
- DateTime dt;
- dt = date_time();
- jj_consume_token(0);
- {if (true) return dt;}
- throw new Error("Missing return statement in function");
- }
-
- final public DateTime date_time() throws ParseException {
- Date d; Time t;
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- case 9:
- case 10:
- day_of_week();
- jj_consume_token(3);
- break;
- default:
- jj_la1[1] = jj_gen;
- ;
- }
- d = date();
- t = time();
- {if (true) return new DateTime(
- d.getYear(),
- d.getMonth(),
- d.getDay(),
- t.getHour(),
- t.getMinute(),
- t.getSecond(),
- t.getZone());} // time zone offset
-
- throw new Error("Missing return statement in function");
- }
-
- final public String day_of_week() throws ParseException {
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 4:
- jj_consume_token(4);
- break;
- case 5:
- jj_consume_token(5);
- break;
- case 6:
- jj_consume_token(6);
- break;
- case 7:
- jj_consume_token(7);
- break;
- case 8:
- jj_consume_token(8);
- break;
- case 9:
- jj_consume_token(9);
- break;
- case 10:
- jj_consume_token(10);
- break;
- default:
- jj_la1[2] = jj_gen;
- jj_consume_token(-1);
- throw new ParseException();
- }
- {if (true) return token.image;}
- throw new Error("Missing return statement in function");
- }
-
- final public Date date() throws ParseException {
- int d, m; String y;
- d = day();
- m = month();
- y = year();
- {if (true) return new Date(y, m, d);}
- throw new Error("Missing return statement in function");
- }
-
- final public int day() throws ParseException {
- Token t;
- t = jj_consume_token(DIGITS);
- {if (true) return parseDigits(t);}
- throw new Error("Missing return statement in function");
- }
-
- final public int month() throws ParseException {
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 11:
- jj_consume_token(11);
- {if (true) return 1;}
- break;
- case 12:
- jj_consume_token(12);
- {if (true) return 2;}
- break;
- case 13:
- jj_consume_token(13);
- {if (true) return 3;}
- break;
- case 14:
- jj_consume_token(14);
- {if (true) return 4;}
- break;
- case 15:
- jj_consume_token(15);
- {if (true) return 5;}
- break;
- case 16:
- jj_consume_token(16);
- {if (true) return 6;}
- break;
- case 17:
- jj_consume_token(17);
- {if (true) return 7;}
- break;
- case 18:
- jj_consume_token(18);
- {if (true) return 8;}
- break;
- case 19:
- jj_consume_token(19);
- {if (true) return 9;}
- break;
- case 20:
- jj_consume_token(20);
- {if (true) return 10;}
- break;
- case 21:
- jj_consume_token(21);
- {if (true) return 11;}
- break;
- case 22:
- jj_consume_token(22);
- {if (true) return 12;}
- break;
- default:
- jj_la1[3] = jj_gen;
- jj_consume_token(-1);
- throw new ParseException();
- }
- throw new Error("Missing return statement in function");
- }
-
- final public String year() throws ParseException {
- Token t;
- t = jj_consume_token(DIGITS);
- {if (true) return t.image;}
- throw new Error("Missing return statement in function");
- }
-
- final public Time time() throws ParseException {
- int h, m, s=0, z;
- h = hour();
- jj_consume_token(23);
- m = minute();
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 23:
- jj_consume_token(23);
- s = second();
- break;
- default:
- jj_la1[4] = jj_gen;
- ;
- }
- z = zone();
- {if (true) return new Time(h, m, s, z);}
- throw new Error("Missing return statement in function");
- }
-
- final public int hour() throws ParseException {
- Token t;
- t = jj_consume_token(DIGITS);
- {if (true) return parseDigits(t);}
- throw new Error("Missing return statement in function");
- }
-
- final public int minute() throws ParseException {
- Token t;
- t = jj_consume_token(DIGITS);
- {if (true) return parseDigits(t);}
- throw new Error("Missing return statement in function");
- }
-
- final public int second() throws ParseException {
- Token t;
- t = jj_consume_token(DIGITS);
- {if (true) return parseDigits(t);}
- throw new Error("Missing return statement in function");
- }
-
- final public int zone() throws ParseException {
- Token t, u; int z;
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case OFFSETDIR:
- t = jj_consume_token(OFFSETDIR);
- u = jj_consume_token(DIGITS);
- z=parseDigits(u)*(t.image.equals("-") ? -1 : 1);
- break;
- case 25:
- case 26:
- case 27:
- case 28:
- case 29:
- case 30:
- case 31:
- case 32:
- case 33:
- case 34:
- case MILITARY_ZONE:
- z = obs_zone();
- break;
- default:
- jj_la1[5] = jj_gen;
- jj_consume_token(-1);
- throw new ParseException();
- }
- {if (true) return z;}
- throw new Error("Missing return statement in function");
- }
-
- final public int obs_zone() throws ParseException {
- Token t; int z;
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case 25:
- jj_consume_token(25);
- z=0;
- break;
- case 26:
- jj_consume_token(26);
- z=0;
- break;
- case 27:
- jj_consume_token(27);
- z=-5;
- break;
- case 28:
- jj_consume_token(28);
- z=-4;
- break;
- case 29:
- jj_consume_token(29);
- z=-6;
- break;
- case 30:
- jj_consume_token(30);
- z=-5;
- break;
- case 31:
- jj_consume_token(31);
- z=-7;
- break;
- case 32:
- jj_consume_token(32);
- z=-6;
- break;
- case 33:
- jj_consume_token(33);
- z=-8;
- break;
- case 34:
- jj_consume_token(34);
- z=-7;
- break;
- case MILITARY_ZONE:
- t = jj_consume_token(MILITARY_ZONE);
- z=getMilitaryZoneOffset(t.image.charAt(0));
- break;
- default:
- jj_la1[6] = jj_gen;
- jj_consume_token(-1);
- throw new ParseException();
- }
- {if (true) return z * 100;}
- throw new Error("Missing return statement in function");
- }
-
- public DateTimeParserTokenManager token_source;
- SimpleCharStream jj_input_stream;
- public Token token, jj_nt;
- private int jj_ntk;
- private int jj_gen;
- final private int[] jj_la1 = new int[7];
- static private int[] jj_la1_0;
- static private int[] jj_la1_1;
- static {
- jj_la1_0();
- jj_la1_1();
- }
- private static void jj_la1_0() {
- jj_la1_0 = new int[] {0x2,0x7f0,0x7f0,0x7ff800,0x800000,0xff000000,0xfe000000,};
- }
- private static void jj_la1_1() {
- jj_la1_1 = new int[] {0x0,0x0,0x0,0x0,0x0,0xf,0xf,};
- }
-
- public DateTimeParser(java.io.InputStream stream) {
- this(stream, null);
- }
- public DateTimeParser(java.io.InputStream stream, String encoding) {
- try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
- token_source = new DateTimeParserTokenManager(jj_input_stream);
- token = new Token();
- jj_ntk = -1;
- jj_gen = 0;
- for (int i = 0; i < 7; i++) jj_la1[i] = -1;
- }
-
- public void ReInit(java.io.InputStream stream) {
- ReInit(stream, null);
- }
- public void ReInit(java.io.InputStream stream, String encoding) {
- try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
- token_source.ReInit(jj_input_stream);
- token = new Token();
- jj_ntk = -1;
- jj_gen = 0;
- for (int i = 0; i < 7; i++) jj_la1[i] = -1;
- }
-
- public DateTimeParser(java.io.Reader stream) {
- jj_input_stream = new SimpleCharStream(stream, 1, 1);
- token_source = new DateTimeParserTokenManager(jj_input_stream);
- token = new Token();
- jj_ntk = -1;
- jj_gen = 0;
- for (int i = 0; i < 7; i++) jj_la1[i] = -1;
- }
-
- public void ReInit(java.io.Reader stream) {
- jj_input_stream.ReInit(stream, 1, 1);
- token_source.ReInit(jj_input_stream);
- token = new Token();
- jj_ntk = -1;
- jj_gen = 0;
- for (int i = 0; i < 7; i++) jj_la1[i] = -1;
- }
-
- public DateTimeParser(DateTimeParserTokenManager tm) {
- token_source = tm;
- token = new Token();
- jj_ntk = -1;
- jj_gen = 0;
- for (int i = 0; i < 7; i++) jj_la1[i] = -1;
- }
-
- public void ReInit(DateTimeParserTokenManager tm) {
- token_source = tm;
- token = new Token();
- jj_ntk = -1;
- jj_gen = 0;
- for (int i = 0; i < 7; i++) jj_la1[i] = -1;
- }
-
- final private Token jj_consume_token(int kind) throws ParseException {
- Token oldToken;
- if ((oldToken = token).next != null) token = token.next;
- else token = token.next = token_source.getNextToken();
- jj_ntk = -1;
- if (token.kind == kind) {
- jj_gen++;
- return token;
- }
- token = oldToken;
- jj_kind = kind;
- throw generateParseException();
- }
-
- final public Token getNextToken() {
- if (token.next != null) token = token.next;
- else token = token.next = token_source.getNextToken();
- jj_ntk = -1;
- jj_gen++;
- return token;
- }
-
- final public Token getToken(int index) {
- Token t = token;
- for (int i = 0; i < index; i++) {
- if (t.next != null) t = t.next;
- else t = t.next = token_source.getNextToken();
- }
- return t;
- }
-
- final private int jj_ntk() {
- if ((jj_nt=token.next) == null)
- return (jj_ntk = (token.next=token_source.getNextToken()).kind);
- else
- return (jj_ntk = jj_nt.kind);
- }
-
- private java.util.Vector jj_expentries = new java.util.Vector();
- private int[] jj_expentry;
- private int jj_kind = -1;
-
- public ParseException generateParseException() {
- jj_expentries.removeAllElements();
- boolean[] la1tokens = new boolean[49];
- for (int i = 0; i < 49; i++) {
- la1tokens[i] = false;
- }
- if (jj_kind >= 0) {
- la1tokens[jj_kind] = true;
- jj_kind = -1;
- }
- for (int i = 0; i < 7; i++) {
- if (jj_la1[i] == jj_gen) {
- for (int j = 0; j < 32; j++) {
- if ((jj_la1_0[i] & (1<<j)) != 0) {
- la1tokens[j] = true;
- }
- if ((jj_la1_1[i] & (1<<j)) != 0) {
- la1tokens[32+j] = true;
- }
- }
- }
- }
- for (int i = 0; i < 49; i++) {
- if (la1tokens[i]) {
- jj_expentry = new int[1];
- jj_expentry[0] = i;
- jj_expentries.addElement(jj_expentry);
- }
- }
- int[][] exptokseq = new int[jj_expentries.size()][];
- for (int i = 0; i < jj_expentries.size(); i++) {
- exptokseq[i] = (int[])jj_expentries.elementAt(i);
- }
- return new ParseException(token, exptokseq, tokenImage);
- }
-
- final public void enable_tracing() {
- }
-
- final public void disable_tracing() {
- }
-
-}
diff --git a/src/org/apache/james/mime4j/field/datetime/parser/DateTimeParserConstants.java b/src/org/apache/james/mime4j/field/datetime/parser/DateTimeParserConstants.java
deleted file mode 100644
index 17389d816..000000000
--- a/src/org/apache/james/mime4j/field/datetime/parser/DateTimeParserConstants.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. DateTimeParserConstants.java */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.datetime.parser;
-
-public interface DateTimeParserConstants {
-
- int EOF = 0;
- int OFFSETDIR = 24;
- int MILITARY_ZONE = 35;
- int WS = 36;
- int COMMENT = 38;
- int DIGITS = 46;
- int QUOTEDPAIR = 47;
- int ANY = 48;
-
- int DEFAULT = 0;
- int INCOMMENT = 1;
- int NESTED_COMMENT = 2;
-
- String[] tokenImage = {
- "<EOF>",
- "\"\\r\"",
- "\"\\n\"",
- "\",\"",
- "\"Mon\"",
- "\"Tue\"",
- "\"Wed\"",
- "\"Thu\"",
- "\"Fri\"",
- "\"Sat\"",
- "\"Sun\"",
- "\"Jan\"",
- "\"Feb\"",
- "\"Mar\"",
- "\"Apr\"",
- "\"May\"",
- "\"Jun\"",
- "\"Jul\"",
- "\"Aug\"",
- "\"Sep\"",
- "\"Oct\"",
- "\"Nov\"",
- "\"Dec\"",
- "\":\"",
- "<OFFSETDIR>",
- "\"UT\"",
- "\"GMT\"",
- "\"EST\"",
- "\"EDT\"",
- "\"CST\"",
- "\"CDT\"",
- "\"MST\"",
- "\"MDT\"",
- "\"PST\"",
- "\"PDT\"",
- "<MILITARY_ZONE>",
- "<WS>",
- "\"(\"",
- "\")\"",
- "<token of kind 39>",
- "\"(\"",
- "<token of kind 41>",
- "<token of kind 42>",
- "\"(\"",
- "\")\"",
- "<token of kind 45>",
- "<DIGITS>",
- "<QUOTEDPAIR>",
- "<ANY>",
- };
-
-}
diff --git a/src/org/apache/james/mime4j/field/datetime/parser/DateTimeParserTokenManager.java b/src/org/apache/james/mime4j/field/datetime/parser/DateTimeParserTokenManager.java
deleted file mode 100644
index e75998cf2..000000000
--- a/src/org/apache/james/mime4j/field/datetime/parser/DateTimeParserTokenManager.java
+++ /dev/null
@@ -1,882 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. DateTimeParserTokenManager.java */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.datetime.parser;
-import org.apache.james.mime4j.field.datetime.DateTime;
-import java.util.Calendar;
-
-public class DateTimeParserTokenManager implements DateTimeParserConstants
-{
- // Keeps track of how many levels of comment nesting
- // we've encountered. This is only used when the 2nd
- // level is reached, for example ((this)), not (this).
- // This is because the outermost level must be treated
- // specially anyway, because the outermost ")" has a
- // different token type than inner ")" instances.
- static int commentNest;
- public java.io.PrintStream debugStream = System.out;
- public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
-private final int jjStopStringLiteralDfa_0(int pos, long active0)
-{
- switch (pos)
- {
- case 0:
- if ((active0 & 0x7fe7cf7f0L) != 0L)
- {
- jjmatchedKind = 35;
- return -1;
- }
- return -1;
- case 1:
- if ((active0 & 0x7fe7cf7f0L) != 0L)
- {
- if (jjmatchedPos == 0)
- {
- jjmatchedKind = 35;
- jjmatchedPos = 0;
- }
- return -1;
- }
- return -1;
- default :
- return -1;
- }
-}
-private final int jjStartNfa_0(int pos, long active0)
-{
- return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
-}
-private final int jjStopAtPos(int pos, int kind)
-{
- jjmatchedKind = kind;
- jjmatchedPos = pos;
- return pos + 1;
-}
-private final int jjStartNfaWithStates_0(int pos, int kind, int state)
-{
- jjmatchedKind = kind;
- jjmatchedPos = pos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return pos + 1; }
- return jjMoveNfa_0(state, pos + 1);
-}
-private final int jjMoveStringLiteralDfa0_0()
-{
- switch(curChar)
- {
- case 10:
- return jjStopAtPos(0, 2);
- case 13:
- return jjStopAtPos(0, 1);
- case 40:
- return jjStopAtPos(0, 37);
- case 44:
- return jjStopAtPos(0, 3);
- case 58:
- return jjStopAtPos(0, 23);
- case 65:
- return jjMoveStringLiteralDfa1_0(0x44000L);
- case 67:
- return jjMoveStringLiteralDfa1_0(0x60000000L);
- case 68:
- return jjMoveStringLiteralDfa1_0(0x400000L);
- case 69:
- return jjMoveStringLiteralDfa1_0(0x18000000L);
- case 70:
- return jjMoveStringLiteralDfa1_0(0x1100L);
- case 71:
- return jjMoveStringLiteralDfa1_0(0x4000000L);
- case 74:
- return jjMoveStringLiteralDfa1_0(0x30800L);
- case 77:
- return jjMoveStringLiteralDfa1_0(0x18000a010L);
- case 78:
- return jjMoveStringLiteralDfa1_0(0x200000L);
- case 79:
- return jjMoveStringLiteralDfa1_0(0x100000L);
- case 80:
- return jjMoveStringLiteralDfa1_0(0x600000000L);
- case 83:
- return jjMoveStringLiteralDfa1_0(0x80600L);
- case 84:
- return jjMoveStringLiteralDfa1_0(0xa0L);
- case 85:
- return jjMoveStringLiteralDfa1_0(0x2000000L);
- case 87:
- return jjMoveStringLiteralDfa1_0(0x40L);
- default :
- return jjMoveNfa_0(0, 0);
- }
-}
-private final int jjMoveStringLiteralDfa1_0(long active0)
-{
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) {
- jjStopStringLiteralDfa_0(0, active0);
- return 1;
- }
- switch(curChar)
- {
- case 68:
- return jjMoveStringLiteralDfa2_0(active0, 0x550000000L);
- case 77:
- return jjMoveStringLiteralDfa2_0(active0, 0x4000000L);
- case 83:
- return jjMoveStringLiteralDfa2_0(active0, 0x2a8000000L);
- case 84:
- if ((active0 & 0x2000000L) != 0L)
- return jjStopAtPos(1, 25);
- break;
- case 97:
- return jjMoveStringLiteralDfa2_0(active0, 0xaa00L);
- case 99:
- return jjMoveStringLiteralDfa2_0(active0, 0x100000L);
- case 101:
- return jjMoveStringLiteralDfa2_0(active0, 0x481040L);
- case 104:
- return jjMoveStringLiteralDfa2_0(active0, 0x80L);
- case 111:
- return jjMoveStringLiteralDfa2_0(active0, 0x200010L);
- case 112:
- return jjMoveStringLiteralDfa2_0(active0, 0x4000L);
- case 114:
- return jjMoveStringLiteralDfa2_0(active0, 0x100L);
- case 117:
- return jjMoveStringLiteralDfa2_0(active0, 0x70420L);
- default :
- break;
- }
- return jjStartNfa_0(0, active0);
-}
-private final int jjMoveStringLiteralDfa2_0(long old0, long active0)
-{
- if (((active0 &= old0)) == 0L)
- return jjStartNfa_0(0, old0);
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) {
- jjStopStringLiteralDfa_0(1, active0);
- return 2;
- }
- switch(curChar)
- {
- case 84:
- if ((active0 & 0x4000000L) != 0L)
- return jjStopAtPos(2, 26);
- else if ((active0 & 0x8000000L) != 0L)
- return jjStopAtPos(2, 27);
- else if ((active0 & 0x10000000L) != 0L)
- return jjStopAtPos(2, 28);
- else if ((active0 & 0x20000000L) != 0L)
- return jjStopAtPos(2, 29);
- else if ((active0 & 0x40000000L) != 0L)
- return jjStopAtPos(2, 30);
- else if ((active0 & 0x80000000L) != 0L)
- return jjStopAtPos(2, 31);
- else if ((active0 & 0x100000000L) != 0L)
- return jjStopAtPos(2, 32);
- else if ((active0 & 0x200000000L) != 0L)
- return jjStopAtPos(2, 33);
- else if ((active0 & 0x400000000L) != 0L)
- return jjStopAtPos(2, 34);
- break;
- case 98:
- if ((active0 & 0x1000L) != 0L)
- return jjStopAtPos(2, 12);
- break;
- case 99:
- if ((active0 & 0x400000L) != 0L)
- return jjStopAtPos(2, 22);
- break;
- case 100:
- if ((active0 & 0x40L) != 0L)
- return jjStopAtPos(2, 6);
- break;
- case 101:
- if ((active0 & 0x20L) != 0L)
- return jjStopAtPos(2, 5);
- break;
- case 103:
- if ((active0 & 0x40000L) != 0L)
- return jjStopAtPos(2, 18);
- break;
- case 105:
- if ((active0 & 0x100L) != 0L)
- return jjStopAtPos(2, 8);
- break;
- case 108:
- if ((active0 & 0x20000L) != 0L)
- return jjStopAtPos(2, 17);
- break;
- case 110:
- if ((active0 & 0x10L) != 0L)
- return jjStopAtPos(2, 4);
- else if ((active0 & 0x400L) != 0L)
- return jjStopAtPos(2, 10);
- else if ((active0 & 0x800L) != 0L)
- return jjStopAtPos(2, 11);
- else if ((active0 & 0x10000L) != 0L)
- return jjStopAtPos(2, 16);
- break;
- case 112:
- if ((active0 & 0x80000L) != 0L)
- return jjStopAtPos(2, 19);
- break;
- case 114:
- if ((active0 & 0x2000L) != 0L)
- return jjStopAtPos(2, 13);
- else if ((active0 & 0x4000L) != 0L)
- return jjStopAtPos(2, 14);
- break;
- case 116:
- if ((active0 & 0x200L) != 0L)
- return jjStopAtPos(2, 9);
- else if ((active0 & 0x100000L) != 0L)
- return jjStopAtPos(2, 20);
- break;
- case 117:
- if ((active0 & 0x80L) != 0L)
- return jjStopAtPos(2, 7);
- break;
- case 118:
- if ((active0 & 0x200000L) != 0L)
- return jjStopAtPos(2, 21);
- break;
- case 121:
- if ((active0 & 0x8000L) != 0L)
- return jjStopAtPos(2, 15);
- break;
- default :
- break;
- }
- return jjStartNfa_0(1, active0);
-}
-private final void jjCheckNAdd(int state)
-{
- if (jjrounds[state] != jjround)
- {
- jjstateSet[jjnewStateCnt++] = state;
- jjrounds[state] = jjround;
- }
-}
-private final void jjAddStates(int start, int end)
-{
- do {
- jjstateSet[jjnewStateCnt++] = jjnextStates[start];
- } while (start++ != end);
-}
-private final void jjCheckNAddTwoStates(int state1, int state2)
-{
- jjCheckNAdd(state1);
- jjCheckNAdd(state2);
-}
-private final void jjCheckNAddStates(int start, int end)
-{
- do {
- jjCheckNAdd(jjnextStates[start]);
- } while (start++ != end);
-}
-private final void jjCheckNAddStates(int start)
-{
- jjCheckNAdd(jjnextStates[start]);
- jjCheckNAdd(jjnextStates[start + 1]);
-}
-private final int jjMoveNfa_0(int startState, int curPos)
-{
- int[] nextStates;
- int startsAt = 0;
- jjnewStateCnt = 4;
- int i = 1;
- jjstateSet[0] = startState;
- int j, kind = 0x7fffffff;
- for (;;)
- {
- if (++jjround == 0x7fffffff)
- ReInitRounds();
- if (curChar < 64)
- {
- long l = 1L << curChar;
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if ((0x3ff000000000000L & l) != 0L)
- {
- if (kind > 46)
- kind = 46;
- jjCheckNAdd(3);
- }
- else if ((0x100000200L & l) != 0L)
- {
- if (kind > 36)
- kind = 36;
- jjCheckNAdd(2);
- }
- else if ((0x280000000000L & l) != 0L)
- {
- if (kind > 24)
- kind = 24;
- }
- break;
- case 2:
- if ((0x100000200L & l) == 0L)
- break;
- kind = 36;
- jjCheckNAdd(2);
- break;
- case 3:
- if ((0x3ff000000000000L & l) == 0L)
- break;
- kind = 46;
- jjCheckNAdd(3);
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else if (curChar < 128)
- {
- long l = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if ((0x7fffbfe07fffbfeL & l) != 0L)
- kind = 35;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else
- {
- int i2 = (curChar & 0xff) >> 6;
- long l2 = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- default : break;
- }
- } while(i != startsAt);
- }
- if (kind != 0x7fffffff)
- {
- jjmatchedKind = kind;
- jjmatchedPos = curPos;
- kind = 0x7fffffff;
- }
- ++curPos;
- if ((i = jjnewStateCnt) == (startsAt = 4 - (jjnewStateCnt = startsAt)))
- return curPos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return curPos; }
- }
-}
-private final int jjStopStringLiteralDfa_1(int pos, long active0)
-{
- switch (pos)
- {
- default :
- return -1;
- }
-}
-private final int jjStartNfa_1(int pos, long active0)
-{
- return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1);
-}
-private final int jjStartNfaWithStates_1(int pos, int kind, int state)
-{
- jjmatchedKind = kind;
- jjmatchedPos = pos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return pos + 1; }
- return jjMoveNfa_1(state, pos + 1);
-}
-private final int jjMoveStringLiteralDfa0_1()
-{
- switch(curChar)
- {
- case 40:
- return jjStopAtPos(0, 40);
- case 41:
- return jjStopAtPos(0, 38);
- default :
- return jjMoveNfa_1(0, 0);
- }
-}
-static final long[] jjbitVec0 = {
- 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
-};
-private final int jjMoveNfa_1(int startState, int curPos)
-{
- int[] nextStates;
- int startsAt = 0;
- jjnewStateCnt = 3;
- int i = 1;
- jjstateSet[0] = startState;
- int j, kind = 0x7fffffff;
- for (;;)
- {
- if (++jjround == 0x7fffffff)
- ReInitRounds();
- if (curChar < 64)
- {
- long l = 1L << curChar;
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if (kind > 41)
- kind = 41;
- break;
- case 1:
- if (kind > 39)
- kind = 39;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else if (curChar < 128)
- {
- long l = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if (kind > 41)
- kind = 41;
- if (curChar == 92)
- jjstateSet[jjnewStateCnt++] = 1;
- break;
- case 1:
- if (kind > 39)
- kind = 39;
- break;
- case 2:
- if (kind > 41)
- kind = 41;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else
- {
- int i2 = (curChar & 0xff) >> 6;
- long l2 = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if ((jjbitVec0[i2] & l2) != 0L && kind > 41)
- kind = 41;
- break;
- case 1:
- if ((jjbitVec0[i2] & l2) != 0L && kind > 39)
- kind = 39;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- if (kind != 0x7fffffff)
- {
- jjmatchedKind = kind;
- jjmatchedPos = curPos;
- kind = 0x7fffffff;
- }
- ++curPos;
- if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
- return curPos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return curPos; }
- }
-}
-private final int jjStopStringLiteralDfa_2(int pos, long active0)
-{
- switch (pos)
- {
- default :
- return -1;
- }
-}
-private final int jjStartNfa_2(int pos, long active0)
-{
- return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1);
-}
-private final int jjStartNfaWithStates_2(int pos, int kind, int state)
-{
- jjmatchedKind = kind;
- jjmatchedPos = pos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return pos + 1; }
- return jjMoveNfa_2(state, pos + 1);
-}
-private final int jjMoveStringLiteralDfa0_2()
-{
- switch(curChar)
- {
- case 40:
- return jjStopAtPos(0, 43);
- case 41:
- return jjStopAtPos(0, 44);
- default :
- return jjMoveNfa_2(0, 0);
- }
-}
-private final int jjMoveNfa_2(int startState, int curPos)
-{
- int[] nextStates;
- int startsAt = 0;
- jjnewStateCnt = 3;
- int i = 1;
- jjstateSet[0] = startState;
- int j, kind = 0x7fffffff;
- for (;;)
- {
- if (++jjround == 0x7fffffff)
- ReInitRounds();
- if (curChar < 64)
- {
- long l = 1L << curChar;
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if (kind > 45)
- kind = 45;
- break;
- case 1:
- if (kind > 42)
- kind = 42;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else if (curChar < 128)
- {
- long l = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if (kind > 45)
- kind = 45;
- if (curChar == 92)
- jjstateSet[jjnewStateCnt++] = 1;
- break;
- case 1:
- if (kind > 42)
- kind = 42;
- break;
- case 2:
- if (kind > 45)
- kind = 45;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else
- {
- int i2 = (curChar & 0xff) >> 6;
- long l2 = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if ((jjbitVec0[i2] & l2) != 0L && kind > 45)
- kind = 45;
- break;
- case 1:
- if ((jjbitVec0[i2] & l2) != 0L && kind > 42)
- kind = 42;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- if (kind != 0x7fffffff)
- {
- jjmatchedKind = kind;
- jjmatchedPos = curPos;
- kind = 0x7fffffff;
- }
- ++curPos;
- if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
- return curPos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return curPos; }
- }
-}
-static final int[] jjnextStates = {
-};
-public static final String[] jjstrLiteralImages = {
-"", "\15", "\12", "\54", "\115\157\156", "\124\165\145", "\127\145\144",
-"\124\150\165", "\106\162\151", "\123\141\164", "\123\165\156", "\112\141\156",
-"\106\145\142", "\115\141\162", "\101\160\162", "\115\141\171", "\112\165\156",
-"\112\165\154", "\101\165\147", "\123\145\160", "\117\143\164", "\116\157\166",
-"\104\145\143", "\72", null, "\125\124", "\107\115\124", "\105\123\124", "\105\104\124",
-"\103\123\124", "\103\104\124", "\115\123\124", "\115\104\124", "\120\123\124",
-"\120\104\124", null, null, null, null, null, null, null, null, null, null, null, null, null,
-null, };
-public static final String[] lexStateNames = {
- "DEFAULT",
- "INCOMMENT",
- "NESTED_COMMENT",
-};
-public static final int[] jjnewLexState = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 0, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1,
-};
-static final long[] jjtoToken = {
- 0x400fffffffffL,
-};
-static final long[] jjtoSkip = {
- 0x5000000000L,
-};
-static final long[] jjtoSpecial = {
- 0x1000000000L,
-};
-static final long[] jjtoMore = {
- 0x3fa000000000L,
-};
-protected SimpleCharStream input_stream;
-private final int[] jjrounds = new int[4];
-private final int[] jjstateSet = new int[8];
-StringBuffer image;
-int jjimageLen;
-int lengthOfMatch;
-protected char curChar;
-public DateTimeParserTokenManager(SimpleCharStream stream){
- if (SimpleCharStream.staticFlag)
- throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
- input_stream = stream;
-}
-public DateTimeParserTokenManager(SimpleCharStream stream, int lexState){
- this(stream);
- SwitchTo(lexState);
-}
-public void ReInit(SimpleCharStream stream)
-{
- jjmatchedPos = jjnewStateCnt = 0;
- curLexState = defaultLexState;
- input_stream = stream;
- ReInitRounds();
-}
-private final void ReInitRounds()
-{
- int i;
- jjround = 0x80000001;
- for (i = 4; i-- > 0;)
- jjrounds[i] = 0x80000000;
-}
-public void ReInit(SimpleCharStream stream, int lexState)
-{
- ReInit(stream);
- SwitchTo(lexState);
-}
-public void SwitchTo(int lexState)
-{
- if (lexState >= 3 || lexState < 0)
- throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
- else
- curLexState = lexState;
-}
-
-protected Token jjFillToken()
-{
- Token t = Token.newToken(jjmatchedKind);
- t.kind = jjmatchedKind;
- String im = jjstrLiteralImages[jjmatchedKind];
- t.image = (im == null) ? input_stream.GetImage() : im;
- t.beginLine = input_stream.getBeginLine();
- t.beginColumn = input_stream.getBeginColumn();
- t.endLine = input_stream.getEndLine();
- t.endColumn = input_stream.getEndColumn();
- return t;
-}
-
-int curLexState = 0;
-int defaultLexState = 0;
-int jjnewStateCnt;
-int jjround;
-int jjmatchedPos;
-int jjmatchedKind;
-
-public Token getNextToken()
-{
- int kind;
- Token specialToken = null;
- Token matchedToken;
- int curPos = 0;
-
- EOFLoop :
- for (;;)
- {
- try
- {
- curChar = input_stream.BeginToken();
- }
- catch(java.io.IOException e)
- {
- jjmatchedKind = 0;
- matchedToken = jjFillToken();
- matchedToken.specialToken = specialToken;
- return matchedToken;
- }
- image = null;
- jjimageLen = 0;
-
- for (;;)
- {
- switch(curLexState)
- {
- case 0:
- jjmatchedKind = 0x7fffffff;
- jjmatchedPos = 0;
- curPos = jjMoveStringLiteralDfa0_0();
- break;
- case 1:
- jjmatchedKind = 0x7fffffff;
- jjmatchedPos = 0;
- curPos = jjMoveStringLiteralDfa0_1();
- break;
- case 2:
- jjmatchedKind = 0x7fffffff;
- jjmatchedPos = 0;
- curPos = jjMoveStringLiteralDfa0_2();
- break;
- }
- if (jjmatchedKind != 0x7fffffff)
- {
- if (jjmatchedPos + 1 < curPos)
- input_stream.backup(curPos - jjmatchedPos - 1);
- if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
- {
- matchedToken = jjFillToken();
- matchedToken.specialToken = specialToken;
- if (jjnewLexState[jjmatchedKind] != -1)
- curLexState = jjnewLexState[jjmatchedKind];
- return matchedToken;
- }
- else if ((jjtoSkip[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
- {
- if ((jjtoSpecial[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
- {
- matchedToken = jjFillToken();
- if (specialToken == null)
- specialToken = matchedToken;
- else
- {
- matchedToken.specialToken = specialToken;
- specialToken = (specialToken.next = matchedToken);
- }
- }
- if (jjnewLexState[jjmatchedKind] != -1)
- curLexState = jjnewLexState[jjmatchedKind];
- continue EOFLoop;
- }
- MoreLexicalActions();
- if (jjnewLexState[jjmatchedKind] != -1)
- curLexState = jjnewLexState[jjmatchedKind];
- curPos = 0;
- jjmatchedKind = 0x7fffffff;
- try {
- curChar = input_stream.readChar();
- continue;
- }
- catch (java.io.IOException e1) { }
- }
- int error_line = input_stream.getEndLine();
- int error_column = input_stream.getEndColumn();
- String error_after = null;
- boolean EOFSeen = false;
- try { input_stream.readChar(); input_stream.backup(1); }
- catch (java.io.IOException e1) {
- EOFSeen = true;
- error_after = curPos <= 1 ? "" : input_stream.GetImage();
- if (curChar == '\n' || curChar == '\r') {
- error_line++;
- error_column = 0;
- }
- else
- error_column++;
- }
- if (!EOFSeen) {
- input_stream.backup(1);
- error_after = curPos <= 1 ? "" : input_stream.GetImage();
- }
- throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
- }
- }
-}
-
-void MoreLexicalActions()
-{
- jjimageLen += (lengthOfMatch = jjmatchedPos + 1);
- switch(jjmatchedKind)
- {
- case 39 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- image.deleteCharAt(image.length() - 2);
- break;
- case 40 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- commentNest = 1;
- break;
- case 42 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- image.deleteCharAt(image.length() - 2);
- break;
- case 43 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- ++commentNest;
- break;
- case 44 :
- if (image == null)
- image = new StringBuffer();
- image.append(input_stream.GetSuffix(jjimageLen));
- jjimageLen = 0;
- --commentNest; if (commentNest == 0) SwitchTo(INCOMMENT);
- break;
- default :
- break;
- }
-}
-}
diff --git a/src/org/apache/james/mime4j/field/datetime/parser/ParseException.java b/src/org/apache/james/mime4j/field/datetime/parser/ParseException.java
deleted file mode 100644
index 418699107..000000000
--- a/src/org/apache/james/mime4j/field/datetime/parser/ParseException.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.datetime.parser;
-
-/**
- * This exception is thrown when parse errors are encountered.
- * You can explicitly create objects of this exception type by
- * calling the method generateParseException in the generated
- * parser.
- *
- * You can modify this class to customize your error reporting
- * mechanisms so long as you retain the public fields.
- */
-public class ParseException extends Exception {
-
- /**
- * This constructor is used by the method "generateParseException"
- * in the generated parser. Calling this constructor generates
- * a new object of this type with the fields "currentToken",
- * "expectedTokenSequences", and "tokenImage" set. The boolean
- * flag "specialConstructor" is also set to true to indicate that
- * this constructor was used to create this object.
- * This constructor calls its super class with the empty string
- * to force the "toString" method of parent class "Throwable" to
- * print the error message in the form:
- * ParseException: <result of getMessage>
- */
- public ParseException(Token currentTokenVal,
- int[][] expectedTokenSequencesVal,
- String[] tokenImageVal
- )
- {
- super("");
- specialConstructor = true;
- currentToken = currentTokenVal;
- expectedTokenSequences = expectedTokenSequencesVal;
- tokenImage = tokenImageVal;
- }
-
- /**
- * The following constructors are for use by you for whatever
- * purpose you can think of. Constructing the exception in this
- * manner makes the exception behave in the normal way - i.e., as
- * documented in the class "Throwable". The fields "errorToken",
- * "expectedTokenSequences", and "tokenImage" do not contain
- * relevant information. The JavaCC generated code does not use
- * these constructors.
- */
-
- public ParseException() {
- super();
- specialConstructor = false;
- }
-
- public ParseException(String message) {
- super(message);
- specialConstructor = false;
- }
-
- /**
- * This variable determines which constructor was used to create
- * this object and thereby affects the semantics of the
- * "getMessage" method (see below).
- */
- protected boolean specialConstructor;
-
- /**
- * This is the last token that has been consumed successfully. If
- * this object has been created due to a parse error, the token
- * followng this token will (therefore) be the first error token.
- */
- public Token currentToken;
-
- /**
- * Each entry in this array is an array of integers. Each array
- * of integers represents a sequence of tokens (by their ordinal
- * values) that is expected at this point of the parse.
- */
- public int[][] expectedTokenSequences;
-
- /**
- * This is a reference to the "tokenImage" array of the generated
- * parser within which the parse error occurred. This array is
- * defined in the generated ...Constants interface.
- */
- public String[] tokenImage;
-
- /**
- * This method has the standard behavior when this object has been
- * created using the standard constructors. Otherwise, it uses
- * "currentToken" and "expectedTokenSequences" to generate a parse
- * error message and returns it. If this object has been created
- * due to a parse error, and you do not catch it (it gets thrown
- * from the parser), then this method is called during the printing
- * of the final stack trace, and hence the correct error message
- * gets displayed.
- */
- public String getMessage() {
- if (!specialConstructor) {
- return super.getMessage();
- }
- StringBuffer expected = new StringBuffer();
- int maxSize = 0;
- for (int i = 0; i < expectedTokenSequences.length; i++) {
- if (maxSize < expectedTokenSequences[i].length) {
- maxSize = expectedTokenSequences[i].length;
- }
- for (int j = 0; j < expectedTokenSequences[i].length; j++) {
- expected.append(tokenImage[expectedTokenSequences[i][j]]).append(" ");
- }
- if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
- expected.append("...");
- }
- expected.append(eol).append(" ");
- }
- String retval = "Encountered \"";
- Token tok = currentToken.next;
- for (int i = 0; i < maxSize; i++) {
- if (i != 0) retval += " ";
- if (tok.kind == 0) {
- retval += tokenImage[0];
- break;
- }
- retval += add_escapes(tok.image);
- tok = tok.next;
- }
- retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
- retval += "." + eol;
- if (expectedTokenSequences.length == 1) {
- retval += "Was expecting:" + eol + " ";
- } else {
- retval += "Was expecting one of:" + eol + " ";
- }
- retval += expected.toString();
- return retval;
- }
-
- /**
- * The end of line string for this machine.
- */
- protected String eol = System.getProperty("line.separator", "\n");
-
- /**
- * Used to convert raw characters to their escaped version
- * when these raw version cannot be used as part of an ASCII
- * string literal.
- */
- protected String add_escapes(String str) {
- StringBuffer retval = new StringBuffer();
- char ch;
- for (int i = 0; i < str.length(); i++) {
- switch (str.charAt(i))
- {
- case 0 :
- continue;
- case '\b':
- retval.append("\\b");
- continue;
- case '\t':
- retval.append("\\t");
- continue;
- case '\n':
- retval.append("\\n");
- continue;
- case '\f':
- retval.append("\\f");
- continue;
- case '\r':
- retval.append("\\r");
- continue;
- case '\"':
- retval.append("\\\"");
- continue;
- case '\'':
- retval.append("\\\'");
- continue;
- case '\\':
- retval.append("\\\\");
- continue;
- default:
- if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
- String s = "0000" + Integer.toString(ch, 16);
- retval.append("\\u" + s.substring(s.length() - 4, s.length()));
- } else {
- retval.append(ch);
- }
- continue;
- }
- }
- return retval.toString();
- }
-
-}
diff --git a/src/org/apache/james/mime4j/field/datetime/parser/SimpleCharStream.java b/src/org/apache/james/mime4j/field/datetime/parser/SimpleCharStream.java
deleted file mode 100644
index d44a9018b..000000000
--- a/src/org/apache/james/mime4j/field/datetime/parser/SimpleCharStream.java
+++ /dev/null
@@ -1,454 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.0 */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.datetime.parser;
-
-/**
- * An implementation of interface CharStream, where the stream is assumed to
- * contain only ASCII characters (without unicode processing).
- */
-
-public class SimpleCharStream
-{
- public static final boolean staticFlag = false;
- int bufsize;
- int available;
- int tokenBegin;
- public int bufpos = -1;
- protected int bufline[];
- protected int bufcolumn[];
-
- protected int column = 0;
- protected int line = 1;
-
- protected boolean prevCharIsCR = false;
- protected boolean prevCharIsLF = false;
-
- protected java.io.Reader inputStream;
-
- protected char[] buffer;
- protected int maxNextCharInd = 0;
- protected int inBuf = 0;
- protected int tabSize = 8;
-
- protected void setTabSize(int i) { tabSize = i; }
- protected int getTabSize(int i) { return tabSize; }
-
-
- protected void ExpandBuff(boolean wrapAround)
- {
- char[] newbuffer = new char[bufsize + 2048];
- int newbufline[] = new int[bufsize + 2048];
- int newbufcolumn[] = new int[bufsize + 2048];
-
- try
- {
- if (wrapAround)
- {
- System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
- System.arraycopy(buffer, 0, newbuffer,
- bufsize - tokenBegin, bufpos);
- buffer = newbuffer;
-
- System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
- System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
- bufline = newbufline;
-
- System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
- System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
- bufcolumn = newbufcolumn;
-
- maxNextCharInd = (bufpos += (bufsize - tokenBegin));
- }
- else
- {
- System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
- buffer = newbuffer;
-
- System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
- bufline = newbufline;
-
- System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
- bufcolumn = newbufcolumn;
-
- maxNextCharInd = (bufpos -= tokenBegin);
- }
- }
- catch (Throwable t)
- {
- throw new Error(t.getMessage());
- }
-
-
- bufsize += 2048;
- available = bufsize;
- tokenBegin = 0;
- }
-
- protected void FillBuff() throws java.io.IOException
- {
- if (maxNextCharInd == available)
- {
- if (available == bufsize)
- {
- if (tokenBegin > 2048)
- {
- bufpos = maxNextCharInd = 0;
- available = tokenBegin;
- }
- else if (tokenBegin < 0)
- bufpos = maxNextCharInd = 0;
- else
- ExpandBuff(false);
- }
- else if (available > tokenBegin)
- available = bufsize;
- else if ((tokenBegin - available) < 2048)
- ExpandBuff(true);
- else
- available = tokenBegin;
- }
-
- int i;
- try {
- if ((i = inputStream.read(buffer, maxNextCharInd,
- available - maxNextCharInd)) == -1)
- {
- inputStream.close();
- throw new java.io.IOException();
- }
- else
- maxNextCharInd += i;
- return;
- }
- catch(java.io.IOException e) {
- --bufpos;
- backup(0);
- if (tokenBegin == -1)
- tokenBegin = bufpos;
- throw e;
- }
- }
-
- public char BeginToken() throws java.io.IOException
- {
- tokenBegin = -1;
- char c = readChar();
- tokenBegin = bufpos;
-
- return c;
- }
-
- protected void UpdateLineColumn(char c)
- {
- column++;
-
- if (prevCharIsLF)
- {
- prevCharIsLF = false;
- line += (column = 1);
- }
- else if (prevCharIsCR)
- {
- prevCharIsCR = false;
- if (c == '\n')
- {
- prevCharIsLF = true;
- }
- else
- line += (column = 1);
- }
-
- switch (c)
- {
- case '\r' :
- prevCharIsCR = true;
- break;
- case '\n' :
- prevCharIsLF = true;
- break;
- case '\t' :
- column--;
- column += (tabSize - (column % tabSize));
- break;
- default :
- break;
- }
-
- bufline[bufpos] = line;
- bufcolumn[bufpos] = column;
- }
-
- public char readChar() throws java.io.IOException
- {
- if (inBuf > 0)
- {
- --inBuf;
-
- if (++bufpos == bufsize)
- bufpos = 0;
-
- return buffer[bufpos];
- }
-
- if (++bufpos >= maxNextCharInd)
- FillBuff();
-
- char c = buffer[bufpos];
-
- UpdateLineColumn(c);
- return (c);
- }
-
- /**
- * @deprecated
- * @see #getEndColumn
- */
-
- public int getColumn() {
- return bufcolumn[bufpos];
- }
-
- /**
- * @deprecated
- * @see #getEndLine
- */
-
- public int getLine() {
- return bufline[bufpos];
- }
-
- public int getEndColumn() {
- return bufcolumn[bufpos];
- }
-
- public int getEndLine() {
- return bufline[bufpos];
- }
-
- public int getBeginColumn() {
- return bufcolumn[tokenBegin];
- }
-
- public int getBeginLine() {
- return bufline[tokenBegin];
- }
-
- public void backup(int amount) {
-
- inBuf += amount;
- if ((bufpos -= amount) < 0)
- bufpos += bufsize;
- }
-
- public SimpleCharStream(java.io.Reader dstream, int startline,
- int startcolumn, int buffersize)
- {
- inputStream = dstream;
- line = startline;
- column = startcolumn - 1;
-
- available = bufsize = buffersize;
- buffer = new char[buffersize];
- bufline = new int[buffersize];
- bufcolumn = new int[buffersize];
- }
-
- public SimpleCharStream(java.io.Reader dstream, int startline,
- int startcolumn)
- {
- this(dstream, startline, startcolumn, 4096);
- }
-
- public SimpleCharStream(java.io.Reader dstream)
- {
- this(dstream, 1, 1, 4096);
- }
- public void ReInit(java.io.Reader dstream, int startline,
- int startcolumn, int buffersize)
- {
- inputStream = dstream;
- line = startline;
- column = startcolumn - 1;
-
- if (buffer == null || buffersize != buffer.length)
- {
- available = bufsize = buffersize;
- buffer = new char[buffersize];
- bufline = new int[buffersize];
- bufcolumn = new int[buffersize];
- }
- prevCharIsLF = prevCharIsCR = false;
- tokenBegin = inBuf = maxNextCharInd = 0;
- bufpos = -1;
- }
-
- public void ReInit(java.io.Reader dstream, int startline,
- int startcolumn)
- {
- ReInit(dstream, startline, startcolumn, 4096);
- }
-
- public void ReInit(java.io.Reader dstream)
- {
- ReInit(dstream, 1, 1, 4096);
- }
- public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
- int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
- {
- this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
- }
-
- public SimpleCharStream(java.io.InputStream dstream, int startline,
- int startcolumn, int buffersize)
- {
- this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
- }
-
- public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
- int startcolumn) throws java.io.UnsupportedEncodingException
- {
- this(dstream, encoding, startline, startcolumn, 4096);
- }
-
- public SimpleCharStream(java.io.InputStream dstream, int startline,
- int startcolumn)
- {
- this(dstream, startline, startcolumn, 4096);
- }
-
- public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
- {
- this(dstream, encoding, 1, 1, 4096);
- }
-
- public SimpleCharStream(java.io.InputStream dstream)
- {
- this(dstream, 1, 1, 4096);
- }
-
- public void ReInit(java.io.InputStream dstream, String encoding, int startline,
- int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
- {
- ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
- }
-
- public void ReInit(java.io.InputStream dstream, int startline,
- int startcolumn, int buffersize)
- {
- ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
- }
-
- public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
- {
- ReInit(dstream, encoding, 1, 1, 4096);
- }
-
- public void ReInit(java.io.InputStream dstream)
- {
- ReInit(dstream, 1, 1, 4096);
- }
- public void ReInit(java.io.InputStream dstream, String encoding, int startline,
- int startcolumn) throws java.io.UnsupportedEncodingException
- {
- ReInit(dstream, encoding, startline, startcolumn, 4096);
- }
- public void ReInit(java.io.InputStream dstream, int startline,
- int startcolumn)
- {
- ReInit(dstream, startline, startcolumn, 4096);
- }
- public String GetImage()
- {
- if (bufpos >= tokenBegin)
- return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
- else
- return new String(buffer, tokenBegin, bufsize - tokenBegin) +
- new String(buffer, 0, bufpos + 1);
- }
-
- public char[] GetSuffix(int len)
- {
- char[] ret = new char[len];
-
- if ((bufpos + 1) >= len)
- System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
- else
- {
- System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
- len - bufpos - 1);
- System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
- }
-
- return ret;
- }
-
- public void Done()
- {
- buffer = null;
- bufline = null;
- bufcolumn = null;
- }
-
- /**
- * Method to adjust line and column numbers for the start of a token.
- */
- public void adjustBeginLineColumn(int newLine, int newCol)
- {
- int start = tokenBegin;
- int len;
-
- if (bufpos >= tokenBegin)
- {
- len = bufpos - tokenBegin + inBuf + 1;
- }
- else
- {
- len = bufsize - tokenBegin + bufpos + 1 + inBuf;
- }
-
- int i = 0, j = 0, k = 0;
- int nextColDiff = 0, columnDiff = 0;
-
- while (i < len &&
- bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
- {
- bufline[j] = newLine;
- nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
- bufcolumn[j] = newCol + columnDiff;
- columnDiff = nextColDiff;
- i++;
- }
-
- if (i < len)
- {
- bufline[j] = newLine++;
- bufcolumn[j] = newCol + columnDiff;
-
- while (i++ < len)
- {
- if (bufline[j = start % bufsize] != bufline[++start % bufsize])
- bufline[j] = newLine++;
- else
- bufline[j] = newLine;
- }
- }
-
- line = bufline[j];
- column = bufcolumn[j];
- }
-
-}
diff --git a/src/org/apache/james/mime4j/field/datetime/parser/Token.java b/src/org/apache/james/mime4j/field/datetime/parser/Token.java
deleted file mode 100644
index 52d101ed0..000000000
--- a/src/org/apache/james/mime4j/field/datetime/parser/Token.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.datetime.parser;
-
-/**
- * Describes the input token stream.
- */
-
-public class Token {
-
- /**
- * An integer that describes the kind of this token. This numbering
- * system is determined by JavaCCParser, and a table of these numbers is
- * stored in the file ...Constants.java.
- */
- public int kind;
-
- /**
- * beginLine and beginColumn describe the position of the first character
- * of this token; endLine and endColumn describe the position of the
- * last character of this token.
- */
- public int beginLine, beginColumn, endLine, endColumn;
-
- /**
- * The string image of the token.
- */
- public String image;
-
- /**
- * A reference to the next regular (non-special) token from the input
- * stream. If this is the last token from the input stream, or if the
- * token manager has not read tokens beyond this one, this field is
- * set to null. This is true only if this token is also a regular
- * token. Otherwise, see below for a description of the contents of
- * this field.
- */
- public Token next;
-
- /**
- * This field is used to access special tokens that occur prior to this
- * token, but after the immediately preceding regular (non-special) token.
- * If there are no such special tokens, this field is set to null.
- * When there are more than one such special token, this field refers
- * to the last of these special tokens, which in turn refers to the next
- * previous special token through its specialToken field, and so on
- * until the first special token (whose specialToken field is null).
- * The next fields of special tokens refer to other special tokens that
- * immediately follow it (without an intervening regular token). If there
- * is no such token, this field is null.
- */
- public Token specialToken;
-
- /**
- * Returns the image.
- */
- public String toString()
- {
- return image;
- }
-
- /**
- * Returns a new Token object, by default. However, if you want, you
- * can create and return subclass objects based on the value of ofKind.
- * Simply add the cases to the switch for all those special cases.
- * For example, if you have a subclass of Token called IDToken that
- * you want to create if ofKind is ID, simlpy add something like :
- *
- * case MyParserConstants.ID : return new IDToken();
- *
- * to the following switch statement. Then you can cast matchedToken
- * variable to the appropriate type and use it in your lexical actions.
- */
- public static final Token newToken(int ofKind)
- {
- switch(ofKind)
- {
- default : return new Token();
- }
- }
-
-}
diff --git a/src/org/apache/james/mime4j/field/datetime/parser/TokenMgrError.java b/src/org/apache/james/mime4j/field/datetime/parser/TokenMgrError.java
deleted file mode 100644
index 973255070..000000000
--- a/src/org/apache/james/mime4j/field/datetime/parser/TokenMgrError.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */
-/*
- * Copyright 2004 the mime4j project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.james.mime4j.field.datetime.parser;
-
-public class TokenMgrError extends Error
-{
- /*
- * Ordinals for various reasons why an Error of this type can be thrown.
- */
-
- /**
- * Lexical error occured.
- */
- static final int LEXICAL_ERROR = 0;
-
- /**
- * An attempt wass made to create a second instance of a static token manager.
- */
- static final int STATIC_LEXER_ERROR = 1;
-
- /**
- * Tried to change to an invalid lexical state.
- */
- static final int INVALID_LEXICAL_STATE = 2;
-
- /**
- * Detected (and bailed out of) an infinite loop in the token manager.
- */
- static final int LOOP_DETECTED = 3;
-
- /**
- * Indicates the reason why the exception is thrown. It will have
- * one of the above 4 values.
- */
- int errorCode;
-
- /**
- * Replaces unprintable characters by their espaced (or unicode escaped)
- * equivalents in the given string
- */
- protected static final String addEscapes(String str) {
- StringBuffer retval = new StringBuffer();
- char ch;
- for (int i = 0; i < str.length(); i++) {
- switch (str.charAt(i))
- {
- case 0 :
- continue;
- case '\b':
- retval.append("\\b");
- continue;
- case '\t':
- retval.append("\\t");
- continue;
- case '\n':
- retval.append("\\n");
- continue;
- case '\f':
- retval.append("\\f");
- continue;
- case '\r':
- retval.append("\\r");
- continue;
- case '\"':
- retval.append("\\\"");
- continue;
- case '\'':
- retval.append("\\\'");
- continue;
- case '\\':
- retval.append("\\\\");
- continue;
- default:
- if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
- String s = "0000" + Integer.toString(ch, 16);
- retval.append("\\u" + s.substring(s.length() - 4, s.length()));
- } else {
- retval.append(ch);
- }
- continue;
- }
- }
- return retval.toString();
- }
-
- /**
- * Returns a detailed message for the Error when it is thrown by the
- * token manager to indicate a lexical error.
- * Parameters :
- * EOFSeen : indicates if EOF caused the lexicl error
- * curLexState : lexical state in which this error occured
- * errorLine : line number when the error occured
- * errorColumn : column number when the error occured
- * errorAfter : prefix that was seen before this error occured
- * curchar : the offending character
- * Note: You can customize the lexical error message by modifying this method.
- */
- protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
- return("Lexical error at line " +
- errorLine + ", column " +
- errorColumn + ". Encountered: " +
- (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
- "after : \"" + addEscapes(errorAfter) + "\"");
- }
-
- /**
- * You can also modify the body of this method to customize your error messages.
- * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
- * of end-users concern, so you can return something like :
- *
- * "Internal Error : Please file a bug report .... "
- *
- * from this method for such cases in the release version of your parser.
- */
- public String getMessage() {
- return super.getMessage();
- }
-
- /*
- * Constructors of various flavors follow.
- */
-
- public TokenMgrError() {
- }
-
- public TokenMgrError(String message, int reason) {
- super(message);
- errorCode = reason;
- }
-
- public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
- this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
- }
-}
diff --git a/src/org/apache/james/mime4j/message/AbstractBody.java b/src/org/apache/james/mime4j/message/AbstractBody.java
deleted file mode 100644
index d2647ec77..000000000
--- a/src/org/apache/james/mime4j/message/AbstractBody.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.message;
-
-
-/**
- * Abstract <code>Body</code> implementation providing the parent
- * functionality required by bodies.
- *
- *
- * @version $Id: AbstractBody.java,v 1.2 2004/10/02 12:41:11 ntherning Exp $
- */
-public abstract class AbstractBody implements Body {
- private Entity parent = null;
-
- /**
- * @see org.apache.james.mime4j.message.Body#getParent()
- */
- public Entity getParent() {
- return parent;
- }
-
- /**
- * @see org.apache.james.mime4j.message.Body#setParent(org.apache.james.mime4j.message.Entity)
- */
- public void setParent(Entity parent) {
- this.parent = parent;
- }
-
-}
diff --git a/src/org/apache/james/mime4j/message/BinaryBody.java b/src/org/apache/james/mime4j/message/BinaryBody.java
deleted file mode 100644
index bfc992a8f..000000000
--- a/src/org/apache/james/mime4j/message/BinaryBody.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.message;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-
-/**
- * Interface implemented by bodies containing binary data.
- *
- *
- * @version $Id: BinaryBody.java,v 1.3 2004/10/02 12:41:11 ntherning Exp $
- */
-public interface BinaryBody extends Body {
-
- /**
- * Gets a <code>InputStream</code> which reads the bytes of the
- * body.
- *
- * @return the stream.
- * @throws IOException on I/O errors.
- */
- InputStream getInputStream() throws IOException;
-}
diff --git a/src/org/apache/james/mime4j/message/Body.java b/src/org/apache/james/mime4j/message/Body.java
deleted file mode 100644
index 54b8948db..000000000
--- a/src/org/apache/james/mime4j/message/Body.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.message;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Encapsulates the body of an entity (see RFC 2045).
- *
- *
- * @version $Id: Body.java,v 1.4 2004/10/04 15:36:43 ntherning Exp $
- */
-public interface Body {
-
- /**
- * Gets the parent of this body.
- *
- * @return the parent.
- */
- Entity getParent();
-
- /**
- * Sets the parent of this body.
- *
- * @param parent the parent.
- */
- void setParent(Entity parent);
-
- /**
- * Writes this body to the given stream in MIME message format.
- *
- * @param out the stream to write to.
- * @throws IOException on I/O errors.
- */
- void writeTo(OutputStream out) throws IOException;
-}
diff --git a/src/org/apache/james/mime4j/message/BodyPart.java b/src/org/apache/james/mime4j/message/BodyPart.java
deleted file mode 100644
index 474030d7f..000000000
--- a/src/org/apache/james/mime4j/message/BodyPart.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.message;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-
-/**
- * Represents a MIME body part (see RFC 2045).
- *
- *
- * @version $Id: BodyPart.java,v 1.3 2004/10/02 12:41:11 ntherning Exp $
- */
-public class BodyPart extends Entity {
-
- /**
- *
- * @see org.apache.james.mime4j.message.Entity#writeTo(java.io.OutputStream)
- */
- public void writeTo(OutputStream out) throws IOException {
- getHeader().writeTo(out);
- getBody().writeTo(out);
- }
-}
diff --git a/src/org/apache/james/mime4j/message/Entity.java b/src/org/apache/james/mime4j/message/Entity.java
deleted file mode 100644
index 96f2a4875..000000000
--- a/src/org/apache/james/mime4j/message/Entity.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.message;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.apache.james.mime4j.field.ContentTransferEncodingField;
-import org.apache.james.mime4j.field.ContentTypeField;
-import org.apache.james.mime4j.field.Field;
-
-/**
- * MIME entity. An entity has a header and a body (see RFC 2045).
- *
- *
- * @version $Id: Entity.java,v 1.3 2004/10/02 12:41:11 ntherning Exp $
- */
-public abstract class Entity {
- private Header header = null;
- private Body body = null;
- private Entity parent = null;
-
- /**
- * Gets the parent entity of this entity.
- * Returns <code>null</code> if this is the root entity.
- *
- * @return the parent or <code>null</code>.
- */
- public Entity getParent() {
- return parent;
- }
-
- /**
- * Sets the parent entity of this entity.
- *
- * @param parent the parent entity or <code>null</code> if
- * this will be the root entity.
- */
- public void setParent(Entity parent) {
- this.parent = parent;
- }
-
- /**
- * Gets the entity header.
- *
- * @return the header.
- */
- public Header getHeader() {
- return header;
- }
-
- /**
- * Sets the entity header.
- *
- * @param header the header.
- */
- public void setHeader(Header header) {
- this.header = header;
- }
-
- /**
- * Gets the body of this entity.
- *
- * @return the body,
- */
- public Body getBody() {
- return body;
- }
-
- /**
- * Sets the body of this entity.
- *
- * @param body the body.
- */
- public void setBody(Body body) {
- this.body = body;
- body.setParent(this);
- }
-
- /**
- * Determines the MIME type of this <code>Entity</code>. The MIME type
- * is derived by looking at the parent's Content-Type field if no
- * Content-Type field is set for this <code>Entity</code>.
- *
- * @return the MIME type.
- */
- public String getMimeType() {
- ContentTypeField child =
- (ContentTypeField) getHeader().getField(Field.CONTENT_TYPE);
- ContentTypeField parent = getParent() != null
- ? (ContentTypeField) getParent().getHeader().
- getField(Field.CONTENT_TYPE)
- : null;
-
- return ContentTypeField.getMimeType(child, parent);
- }
-
- /**
- * Determines the MIME character set encoding of this <code>Entity</code>.
- *
- * @return the MIME character set encoding.
- */
- public String getCharset() {
- return ContentTypeField.getCharset(
- (ContentTypeField) getHeader().getField(Field.CONTENT_TYPE));
- }
-
- /**
- * Determines the transfer encoding of this <code>Entity</code>.
- *
- * @return the transfer encoding.
- */
- public String getContentTransferEncoding() {
- ContentTransferEncodingField f = (ContentTransferEncodingField)
- getHeader().getField(Field.CONTENT_TRANSFER_ENCODING);
-
- return ContentTransferEncodingField.getEncoding(f);
- }
-
- /**
- * Determines if the MIME type of this <code>Entity</code> matches the
- * given one. MIME types are case-insensitive.
- *
- * @param type the MIME type to match against.
- * @return <code>true</code> on match, <code>false</code> otherwise.
- */
- public boolean isMimeType(String type) {
- return getMimeType().equalsIgnoreCase(type);
- }
-
- /**
- * Determines if the MIME type of this <code>Entity</code> is
- * <code>multipart/*</code>. Since multipart-entities must have
- * a boundary parameter in the <code>Content-Type</code> field this
- * method returns <code>false</code> if no boundary exists.
- *
- * @return <code>true</code> on match, <code>false</code> otherwise.
- */
- public boolean isMultipart() {
- ContentTypeField f =
- (ContentTypeField) getHeader().getField(Field.CONTENT_TYPE);
- return f != null && f.getBoundary() != null
- && getMimeType().startsWith(ContentTypeField.TYPE_MULTIPART_PREFIX);
- }
-
- /**
- * Write the content to the given outputstream
- *
- * @param out the outputstream to write to
- * @throws IOException
- */
- public abstract void writeTo(OutputStream out) throws IOException;
-}
diff --git a/src/org/apache/james/mime4j/message/Header.java b/src/org/apache/james/mime4j/message/Header.java
deleted file mode 100644
index 90a0ef480..000000000
--- a/src/org/apache/james/mime4j/message/Header.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.message;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.apache.james.mime4j.AbstractContentHandler;
-import org.apache.james.mime4j.MimeStreamParser;
-import org.apache.james.mime4j.field.ContentTypeField;
-import org.apache.james.mime4j.field.Field;
-import org.apache.james.mime4j.util.CharsetUtil;
-
-
-/**
- * The header of an entity (see RFC 2045).
- *
- *
- * @version $Id: Header.java,v 1.3 2004/10/04 15:36:44 ntherning Exp $
- */
-public class Header {
- private List fields = new LinkedList();
- private HashMap fieldMap = new HashMap();
-
- /**
- * Creates a new empty <code>Header</code>.
- */
- public Header() {
- }
-
- /**
- * Creates a new <code>Header</code> from the specified stream.
- *
- * @param is the stream to read the header from.
- */
- public Header(InputStream is) throws IOException {
- final MimeStreamParser parser = new MimeStreamParser();
- parser.setContentHandler(new AbstractContentHandler() {
- public void endHeader() {
- parser.stop();
- }
- public void field(String fieldData) {
- addField(Field.parse(fieldData));
- }
- });
- parser.parse(is);
- }
-
- /**
- * Adds a field to the end of the list of fields.
- *
- * @param field the field to add.
- */
- public void addField(Field field) {
- List values = (List) fieldMap.get(field.getName().toLowerCase());
- if (values == null) {
- values = new LinkedList();
- fieldMap.put(field.getName().toLowerCase(), values);
- }
- values.add(field);
- fields.add(field);
- }
-
- /**
- * Gets the fields of this header. The returned list will not be
- * modifiable.
- *
- * @return the list of <code>Field</code> objects.
- */
- public List getFields() {
- return Collections.unmodifiableList(fields);
- }
-
- /**
- * Gets a <code>Field</code> given a field name. If there are multiple
- * such fields defined in this header the first one will be returned.
- *
- * @param name the field name (e.g. From, Subject).
- * @return the field or <code>null</code> if none found.
- */
- public Field getField(String name) {
- List l = (List) fieldMap.get(name.toLowerCase());
- if (l != null && !l.isEmpty()) {
- return (Field) l.get(0);
- }
- return null;
- }
-
- /**
- * Gets all <code>Field</code>s having the specified field name.
- *
- * @param name the field name (e.g. From, Subject).
- * @return the list of fields.
- */
- public List getFields(String name) {
- List l = (List) fieldMap.get(name.toLowerCase());
- return Collections.unmodifiableList(l);
- }
-
- /**
- * Return Header Object as String representation. Each headerline is
- * seperated by "\r\n"
- *
- * @return headers
- */
- public String toString() {
- StringBuffer str = new StringBuffer();
- for (Iterator it = fields.iterator(); it.hasNext();) {
- str.append(it.next().toString());
- str.append("\r\n");
- }
- return str.toString();
- }
-
-
- /**
- * Write the Header to the given OutputStream
- *
- * @param out the OutputStream to write to
- * @throws IOException
- */
- public void writeTo(OutputStream out) throws IOException {
- String charString = ((ContentTypeField) getField(Field.CONTENT_TYPE)).getCharset();
-
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, CharsetUtil.getCharset(charString)),8192);
- writer.write(toString()+ "\r\n");
- writer.flush();
- }
-
-}
diff --git a/src/org/apache/james/mime4j/message/MemoryBinaryBody.java b/src/org/apache/james/mime4j/message/MemoryBinaryBody.java
deleted file mode 100644
index 0db44e199..000000000
--- a/src/org/apache/james/mime4j/message/MemoryBinaryBody.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.message;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.james.mime4j.util.TempPath;
-import org.apache.james.mime4j.util.TempStorage;
-
-
-/**
- * Binary body backed by a {@link org.apache.james.mime4j.util.TempFile}.
- *
- *
- * @version $Id: TempFileBinaryBody.java,v 1.2 2004/10/02 12:41:11 ntherning Exp $
- */
-class MemoryBinaryBody extends AbstractBody implements BinaryBody {
- private static Log log = LogFactory.getLog(MemoryBinaryBody.class);
-
- private Entity parent = null;
- private byte[] tempFile = null;
-
- /**
- * Use the given InputStream to build the TemporyFileBinaryBody
- *
- * @param is the InputStream to use as source
- * @throws IOException
- */
- public MemoryBinaryBody(InputStream is) throws IOException {
-
- TempPath tempPath = TempStorage.getInstance().getRootTempPath();
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- IOUtils.copy(is, out);
- out.close();
- tempFile = out.toByteArray();
- }
-
- /**
- * @see org.apache.james.mime4j.message.AbstractBody#getParent()
- */
- public Entity getParent() {
- return parent;
- }
-
- /**
- * @see org.apache.james.mime4j.message.AbstractBody#setParent(org.apache.james.mime4j.message.Entity)
- */
- public void setParent(Entity parent) {
- this.parent = parent;
- }
-
- /**
- * @see org.apache.james.mime4j.message.BinaryBody#getInputStream()
- */
- public InputStream getInputStream() throws IOException {
- return new ByteArrayInputStream(tempFile);
- }
-
- /**
- * @see org.apache.james.mime4j.message.Body#writeTo(java.io.OutputStream)
- */
- public void writeTo(OutputStream out) throws IOException {
- IOUtils.copy(getInputStream(),out);
- }
-}
diff --git a/src/org/apache/james/mime4j/message/MemoryTextBody.java b/src/org/apache/james/mime4j/message/MemoryTextBody.java
deleted file mode 100644
index e5e9d9d72..000000000
--- a/src/org/apache/james/mime4j/message/MemoryTextBody.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.message;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.UnsupportedEncodingException;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.james.mime4j.util.CharsetUtil;
-import org.apache.james.mime4j.util.TempPath;
-import org.apache.james.mime4j.util.TempStorage;
-
-
-/**
- * Text body backed by a {@link org.apache.james.mime4j.util.TempFile}.
- *
- *
- * @version $Id: TempFileTextBody.java,v 1.3 2004/10/25 07:26:46 ntherning Exp $
- */
-class MemoryTextBody extends AbstractBody implements TextBody {
- private static Log log = LogFactory.getLog(MemoryTextBody.class);
-
- private String mimeCharset = null;
- private byte[] tempFile = null;
-
- public MemoryTextBody(InputStream is) throws IOException {
- this(is, null);
- }
-
- public MemoryTextBody(InputStream is, String mimeCharset)
- throws IOException {
-
- this.mimeCharset = mimeCharset;
-
- TempPath tempPath = TempStorage.getInstance().getRootTempPath();
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- IOUtils.copy(is, out);
- out.close();
- tempFile = out.toByteArray();
- }
-
- /**
- * @see org.apache.james.mime4j.message.TextBody#getReader()
- */
- public Reader getReader() throws UnsupportedEncodingException, IOException {
- String javaCharset = null;
- if (mimeCharset != null) {
- javaCharset = CharsetUtil.toJavaCharset(mimeCharset);
- }
-
- if (javaCharset == null) {
- javaCharset = "ISO-8859-1";
-
- if (log.isWarnEnabled()) {
- if (mimeCharset == null) {
- log.warn("No MIME charset specified. Using " + javaCharset
- + " instead.");
- } else {
- log.warn("MIME charset '" + mimeCharset + "' has no "
- + "corresponding Java charset. Using " + javaCharset
- + " instead.");
- }
- }
- }
- /*
- if (log.isWarnEnabled()) {
- if (mimeCharset == null) {
- log.warn("No MIME charset specified. Using the "
- + "platform's default charset.");
- } else {
- log.warn("MIME charset '" + mimeCharset + "' has no "
- + "corresponding Java charset. Using the "
- + "platform's default charset.");
- }
- }
-
- return new InputStreamReader(tempFile.getInputStream());
- }*/
-
- return new InputStreamReader(new ByteArrayInputStream(tempFile), javaCharset);
- }
-
-
- /**
- * @see org.apache.james.mime4j.message.Body#writeTo(java.io.OutputStream)
- */
- public void writeTo(OutputStream out) throws IOException {
- IOUtils.copy(new ByteArrayInputStream(tempFile), out);
- }
-}
diff --git a/src/org/apache/james/mime4j/message/Message.java b/src/org/apache/james/mime4j/message/Message.java
deleted file mode 100644
index fc28c586a..000000000
--- a/src/org/apache/james/mime4j/message/Message.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.message;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Stack;
-
-import org.apache.james.mime4j.BodyDescriptor;
-import org.apache.james.mime4j.ContentHandler;
-import org.apache.james.mime4j.MimeStreamParser;
-import org.apache.james.mime4j.decoder.Base64InputStream;
-import org.apache.james.mime4j.decoder.QuotedPrintableInputStream;
-import org.apache.james.mime4j.field.Field;
-import org.apache.james.mime4j.field.UnstructuredField;
-
-
-/**
- * Represents a MIME message. The following code parses a stream into a
- * <code>Message</code> object.
- *
- * <pre>
- * Message msg = new Message(new BufferedInputStream(
- * new FileInputStream("mime.msg")));
- * </pre>
- *
- *
- *
- * @version $Id: Message.java,v 1.3 2004/10/02 12:41:11 ntherning Exp $
- */
-public class Message extends Entity implements Body {
-
- /**
- * Creates a new empty <code>Message</code>.
- */
- public Message() {
- }
-
- /**
- * Parses the specified MIME message stream into a <code>Message</code>
- * instance.
- *
- * @param is the stream to parse.
- * @throws IOException on I/O errors.
- */
- public Message(InputStream is) throws IOException {
- MimeStreamParser parser = new MimeStreamParser();
- parser.setContentHandler(new MessageBuilder());
- parser.parse(is);
- }
-
-
- /**
- * Gets the <code>Subject</code> field.
- *
- * @return the <code>Subject</code> field or <code>null</code> if it
- * doesn't exist.
- */
- public UnstructuredField getSubject() {
- return (UnstructuredField) getHeader().getField(Field.SUBJECT);
- }
-
- /**
- *
- * @see org.apache.james.mime4j.message.Entity#writeTo(java.io.OutputStream)
- */
- public void writeTo(OutputStream out) throws IOException {
- getHeader().writeTo(out);
-
- Body body = getBody();
- if (body instanceof Multipart) {
- Multipart mp = (Multipart) body;
- mp.writeTo(out);
- } else {
- body.writeTo(out);
- }
- }
-
-
- private class MessageBuilder implements ContentHandler {
- private Stack stack = new Stack();
-
- public MessageBuilder() {
- }
-
- private void expect(Class c) {
- if (!c.isInstance(stack.peek())) {
- throw new IllegalStateException("Internal stack error: "
- + "Expected '" + c.getName() + "' found '"
- + stack.peek().getClass().getName() + "'");
- }
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#startMessage()
- */
- public void startMessage() {
- if (stack.isEmpty()) {
- stack.push(Message.this);
- } else {
- expect(Entity.class);
- Message m = new Message();
- ((Entity) stack.peek()).setBody(m);
- stack.push(m);
- }
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#endMessage()
- */
- public void endMessage() {
- expect(Message.class);
- stack.pop();
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#startHeader()
- */
- public void startHeader() {
- stack.push(new Header());
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#field(java.lang.String)
- */
- public void field(String fieldData) {
- expect(Header.class);
- ((Header) stack.peek()).addField(Field.parse(fieldData));
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#endHeader()
- */
- public void endHeader() {
- expect(Header.class);
- Header h = (Header) stack.pop();
- expect(Entity.class);
- ((Entity) stack.peek()).setHeader(h);
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#startMultipart(org.apache.james.mime4j.BodyDescriptor)
- */
- public void startMultipart(BodyDescriptor bd) {
- expect(Entity.class);
-
- Entity e = (Entity) stack.peek();
- Multipart multiPart = new Multipart();
- e.setBody(multiPart);
- stack.push(multiPart);
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#body(org.apache.james.mime4j.BodyDescriptor, java.io.InputStream)
- */
- public void body(BodyDescriptor bd, InputStream is) throws IOException {
- expect(Entity.class);
-
- String enc = bd.getTransferEncoding();
- if ("base64".equals(enc)) {
- is = new Base64InputStream(is);
- } else if ("quoted-printable".equals(enc)) {
- is = new QuotedPrintableInputStream(is);
- }
-
- Body body = null;
- if (bd.getMimeType().startsWith("text/")) {
- body = new MemoryTextBody(is, bd.getCharset());
- } else {
- body = new MemoryBinaryBody(is);
- }
-
- ((Entity) stack.peek()).setBody(body);
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#endMultipart()
- */
- public void endMultipart() {
- stack.pop();
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#startBodyPart()
- */
- public void startBodyPart() {
- expect(Multipart.class);
-
- BodyPart bodyPart = new BodyPart();
- ((Multipart) stack.peek()).addBodyPart(bodyPart);
- stack.push(bodyPart);
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#endBodyPart()
- */
- public void endBodyPart() {
- expect(BodyPart.class);
- stack.pop();
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#epilogue(java.io.InputStream)
- */
- public void epilogue(InputStream is) throws IOException {
- expect(Multipart.class);
- StringBuffer sb = new StringBuffer();
- int b;
- while ((b = is.read()) != -1) {
- sb.append((char) b);
- }
- ((Multipart) stack.peek()).setEpilogue(sb.toString());
- }
-
- /**
- * @see org.apache.james.mime4j.ContentHandler#preamble(java.io.InputStream)
- */
- public void preamble(InputStream is) throws IOException {
- expect(Multipart.class);
- StringBuffer sb = new StringBuffer();
- int b;
- while ((b = is.read()) != -1) {
- sb.append((char) b);
- }
- ((Multipart) stack.peek()).setPreamble(sb.toString());
- }
-
- /**
- * TODO: Implement me
- *
- * @see org.apache.james.mime4j.ContentHandler#raw(java.io.InputStream)
- */
- public void raw(InputStream is) throws IOException {
- throw new UnsupportedOperationException("Not supported");
- }
-
- }
-}
diff --git a/src/org/apache/james/mime4j/message/Multipart.java b/src/org/apache/james/mime4j/message/Multipart.java
deleted file mode 100644
index 3c4b519c4..000000000
--- a/src/org/apache/james/mime4j/message/Multipart.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.message;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.apache.james.mime4j.field.ContentTypeField;
-import org.apache.james.mime4j.field.Field;
-import org.apache.james.mime4j.util.CharsetUtil;
-
-/**
- * Represents a MIME multipart body (see RFC 2045).A multipart body has a
- * ordered list of body parts. The multipart body also has a preamble and
- * epilogue. The preamble consists of whatever characters appear before the
- * first body part while the epilogue consists of whatever characters come
- * after the last body part.
- *
- *
- * @version $Id: Multipart.java,v 1.3 2004/10/02 12:41:11 ntherning Exp $
- */
-public class Multipart implements Body {
- private String preamble = "";
- private String epilogue = "";
- private List bodyParts = new LinkedList();
- private Entity parent = null;
- private String subType = "alternative";
-
- /**
- * Creates a new empty <code>Multipart</code> instance.
- */
- public Multipart() {
- }
-
- /**
- * Gets the multipart sub-type. E.g. <code>alternative</code> (the default)
- * or <code>parallel</code>. See RFC 2045 for common sub-types and their
- * meaning.
- *
- * @return the multipart sub-type.
- */
- public String getSubType() {
- return subType;
- }
-
- /**
- * Sets the multipart sub-type. E.g. <code>alternative</code>
- * or <code>parallel</code>. See RFC 2045 for common sub-types and their
- * meaning.
- *
- * @param subType the sub-type.
- */
- public void setSubType(String subType) {
- this.subType = subType;
- }
-
- /**
- * @see org.apache.james.mime4j.message.Body#getParent()
- */
- public Entity getParent() {
- return parent;
- }
-
- /**
- * @see org.apache.james.mime4j.message.Body#setParent(org.apache.james.mime4j.message.Entity)
- */
- public void setParent(Entity parent) {
- this.parent = parent;
- for (Iterator it = bodyParts.iterator(); it.hasNext();) {
- ((BodyPart) it.next()).setParent(parent);
- }
- }
-
- /**
- * Gets the epilogue.
- *
- * @return the epilogue.
- */
- public String getEpilogue() {
- return epilogue;
- }
-
- /**
- * Sets the epilogue.
- *
- * @param epilogue the epilogue.
- */
- public void setEpilogue(String epilogue) {
- this.epilogue = epilogue;
- }
-
- /**
- * Gets the list of body parts. The list is immutable.
- *
- * @return the list of <code>BodyPart</code> objects.
- */
- public List getBodyParts() {
- return Collections.unmodifiableList(bodyParts);
- }
-
- /**
- * Sets the list of body parts.
- *
- * @param bodyParts the new list of <code>BodyPart</code> objects.
- */
- public void setBodyParts(List bodyParts) {
- this.bodyParts = bodyParts;
- for (Iterator it = bodyParts.iterator(); it.hasNext();) {
- ((BodyPart) it.next()).setParent(parent);
- }
- }
-
- /**
- * Adds a body part to the end of the list of body parts.
- *
- * @param bodyPart the body part.
- */
- public void addBodyPart(BodyPart bodyPart) {
- bodyParts.add(bodyPart);
- bodyPart.setParent(parent);
- }
-
- /**
- * Gets the preamble.
- *
- * @return the preamble.
- */
- public String getPreamble() {
- return preamble;
- }
-
- /**
- * Sets the preamble.
- *
- * @param preamble the preamble.
- */
- public void setPreamble(String preamble) {
- this.preamble = preamble;
- }
-
- /**
- *
- * @see org.apache.james.mime4j.message.Body#writeTo(java.io.OutputStream)
- */
- public void writeTo(OutputStream out) throws IOException {
- String boundary = getBoundary();
- List bodyParts = getBodyParts();
-
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, CharsetUtil.getCharset(getCharset())),8192);
-
- writer.write(getPreamble() + "\r\n");
-
- for (int i = 0; i < bodyParts.size(); i++) {
- writer.write(boundary + "\r\n");
- ((BodyPart) bodyParts.get(i)).writeTo(out);
- }
-
- writer.write(getEpilogue() + "\r\n");
- writer.write(boundary + "--" + "\r\n");
-
- }
-
- /**
- * Return the boundory of the parent Entity
- *
- * @return boundery
- */
- private String getBoundary() {
- Entity e = getParent();
- ContentTypeField cField = (ContentTypeField) e.getHeader().getField(
- Field.CONTENT_TYPE);
- return cField.getBoundary();
- }
-
- private String getCharset() {
- Entity e = getParent();
- String charString = ((ContentTypeField) e.getHeader().getField(Field.CONTENT_TYPE)).getCharset();
- return charString;
- }
-}
diff --git a/src/org/apache/james/mime4j/message/TempFileBinaryBody.java b/src/org/apache/james/mime4j/message/TempFileBinaryBody.java
deleted file mode 100644
index 3ded83db8..000000000
--- a/src/org/apache/james/mime4j/message/TempFileBinaryBody.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.message;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.james.mime4j.util.TempFile;
-import org.apache.james.mime4j.util.TempPath;
-import org.apache.james.mime4j.util.TempStorage;
-
-
-/**
- * Binary body backed by a {@link org.apache.james.mime4j.util.TempFile}.
- *
- *
- * @version $Id: TempFileBinaryBody.java,v 1.2 2004/10/02 12:41:11 ntherning Exp $
- */
-class TempFileBinaryBody extends AbstractBody implements BinaryBody {
- private static Log log = LogFactory.getLog(TempFileBinaryBody.class);
-
- private Entity parent = null;
- private TempFile tempFile = null;
-
- /**
- * Use the given InputStream to build the TemporyFileBinaryBody
- *
- * @param is the InputStream to use as source
- * @throws IOException
- */
- public TempFileBinaryBody(InputStream is) throws IOException {
-
- TempPath tempPath = TempStorage.getInstance().getRootTempPath();
- tempFile = tempPath.createTempFile("attachment", ".bin");
-
- OutputStream out = tempFile.getOutputStream();
- IOUtils.copy(is, out);
- out.close();
- }
-
- /**
- * @see org.apache.james.mime4j.message.AbstractBody#getParent()
- */
- public Entity getParent() {
- return parent;
- }
-
- /**
- * @see org.apache.james.mime4j.message.AbstractBody#setParent(org.apache.james.mime4j.message.Entity)
- */
- public void setParent(Entity parent) {
- this.parent = parent;
- }
-
- /**
- * @see org.apache.james.mime4j.message.BinaryBody#getInputStream()
- */
- public InputStream getInputStream() throws IOException {
- return tempFile.getInputStream();
- }
-
- /**
- * @see org.apache.james.mime4j.message.Body#writeTo(java.io.OutputStream)
- */
- public void writeTo(OutputStream out) throws IOException {
- IOUtils.copy(getInputStream(),out);
- }
-}
diff --git a/src/org/apache/james/mime4j/message/TempFileTextBody.java b/src/org/apache/james/mime4j/message/TempFileTextBody.java
deleted file mode 100644
index 0b3b70c25..000000000
--- a/src/org/apache/james/mime4j/message/TempFileTextBody.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.message;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.UnsupportedEncodingException;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.james.mime4j.util.CharsetUtil;
-import org.apache.james.mime4j.util.TempFile;
-import org.apache.james.mime4j.util.TempPath;
-import org.apache.james.mime4j.util.TempStorage;
-
-
-/**
- * Text body backed by a {@link org.apache.james.mime4j.util.TempFile}.
- *
- *
- * @version $Id: TempFileTextBody.java,v 1.3 2004/10/25 07:26:46 ntherning Exp $
- */
-class TempFileTextBody extends AbstractBody implements TextBody {
- private static Log log = LogFactory.getLog(TempFileTextBody.class);
-
- private String mimeCharset = null;
- private TempFile tempFile = null;
-
- public TempFileTextBody(InputStream is) throws IOException {
- this(is, null);
- }
-
- public TempFileTextBody(InputStream is, String mimeCharset)
- throws IOException {
-
- this.mimeCharset = mimeCharset;
-
- TempPath tempPath = TempStorage.getInstance().getRootTempPath();
- tempFile = tempPath.createTempFile("attachment", ".txt");
-
- OutputStream out = tempFile.getOutputStream();
- IOUtils.copy(is, out);
- out.close();
- }
-
- /**
- * @see org.apache.james.mime4j.message.TextBody#getReader()
- */
- public Reader getReader() throws UnsupportedEncodingException, IOException {
- String javaCharset = null;
- if (mimeCharset != null) {
- javaCharset = CharsetUtil.toJavaCharset(mimeCharset);
- }
-
- if (javaCharset == null) {
- javaCharset = "ISO-8859-1";
-
- if (log.isWarnEnabled()) {
- if (mimeCharset == null) {
- log.warn("No MIME charset specified. Using " + javaCharset
- + " instead.");
- } else {
- log.warn("MIME charset '" + mimeCharset + "' has no "
- + "corresponding Java charset. Using " + javaCharset
- + " instead.");
- }
- }
- }
- /*
- if (log.isWarnEnabled()) {
- if (mimeCharset == null) {
- log.warn("No MIME charset specified. Using the "
- + "platform's default charset.");
- } else {
- log.warn("MIME charset '" + mimeCharset + "' has no "
- + "corresponding Java charset. Using the "
- + "platform's default charset.");
- }
- }
-
- return new InputStreamReader(tempFile.getInputStream());
- }*/
-
- return new InputStreamReader(tempFile.getInputStream(), javaCharset);
- }
-
-
- /**
- * @see org.apache.james.mime4j.message.Body#writeTo(java.io.OutputStream)
- */
- public void writeTo(OutputStream out) throws IOException {
- IOUtils.copy(tempFile.getInputStream(), out);
- }
-}
diff --git a/src/org/apache/james/mime4j/message/TextBody.java b/src/org/apache/james/mime4j/message/TextBody.java
deleted file mode 100644
index 4fe714466..000000000
--- a/src/org/apache/james/mime4j/message/TextBody.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.message;
-
-import java.io.IOException;
-import java.io.Reader;
-
-
-/**
- * Encapsulates the contents of a <code>text/*</code> entity body.
- *
- *
- * @version $Id: TextBody.java,v 1.3 2004/10/02 12:41:11 ntherning Exp $
- */
-public interface TextBody extends Body {
-
- /**
- * Gets a <code>Reader</code> which may be used to read out the contents
- * of this body.
- *
- * @return the <code>Reader</code>.
- * @throws IOException on I/O errors.
- */
- Reader getReader() throws IOException;
-}
diff --git a/src/org/apache/james/mime4j/util/CharsetUtil.java b/src/org/apache/james/mime4j/util/CharsetUtil.java
deleted file mode 100644
index f5026b1f8..000000000
--- a/src/org/apache/james/mime4j/util/CharsetUtil.java
+++ /dev/null
@@ -1,1178 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.util;
-
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.IllegalCharsetNameException;
-import java.nio.charset.UnsupportedCharsetException;
-import java.util.HashMap;
-import java.util.TreeSet;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Utility class for working with character sets. It is somewhat similar to
- * the Java 1.4 <code>java.nio.charset.Charset</code> class but knows many
- * more aliases and is compatible with Java 1.3. It will use a simple detection
- * mechanism to detect what character sets the current VM supports. This will
- * be a sub-set of the character sets listed in the
- * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html">
- * Java 1.5 (J2SE5.0) Supported Encodings</a> document.
- * <p>
- * The <a href="http://www.iana.org/assignments/character-sets">
- * IANA Character Sets</a> document has been used to determine the preferred
- * MIME character set names and to get a list of known aliases.
- * <p>
- * This is a complete list of the character sets known to this class:
- * <table>
- * <tr>
- * <td>Canonical (Java) name</td>
- * <td>MIME preferred</td>
- * <td>Aliases</td>
- * </tr>
- * <tr>
- * <td>ASCII</td>
- * <td>US-ASCII</td>
- * <td>ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ISO646-US us IBM367 cp367 csASCII ascii7 646 iso_646.irv:1983 </td>
- * </tr>
- * <tr>
- * <td>Big5</td>
- * <td>Big5</td>
- * <td>csBig5 CN-Big5 BIG-FIVE BIGFIVE </td>
- * </tr>
- * <tr>
- * <td>Big5_HKSCS</td>
- * <td>Big5-HKSCS</td>
- * <td>big5hkscs </td>
- * </tr>
- * <tr>
- * <td>Big5_Solaris</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp037</td>
- * <td>IBM037</td>
- * <td>ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl csIBM037 </td>
- * </tr>
- * <tr>
- * <td>Cp1006</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1025</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1026</td>
- * <td>IBM1026</td>
- * <td>csIBM1026 </td>
- * </tr>
- * <tr>
- * <td>Cp1046</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1047</td>
- * <td>IBM1047</td>
- * <td>IBM-1047 </td>
- * </tr>
- * <tr>
- * <td>Cp1097</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1098</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1112</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1122</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1123</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1124</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1140</td>
- * <td>IBM01140</td>
- * <td>CCSID01140 CP01140 ebcdic-us-37+euro </td>
- * </tr>
- * <tr>
- * <td>Cp1141</td>
- * <td>IBM01141</td>
- * <td>CCSID01141 CP01141 ebcdic-de-273+euro </td>
- * </tr>
- * <tr>
- * <td>Cp1142</td>
- * <td>IBM01142</td>
- * <td>CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro </td>
- * </tr>
- * <tr>
- * <td>Cp1143</td>
- * <td>IBM01143</td>
- * <td>CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro </td>
- * </tr>
- * <tr>
- * <td>Cp1144</td>
- * <td>IBM01144</td>
- * <td>CCSID01144 CP01144 ebcdic-it-280+euro </td>
- * </tr>
- * <tr>
- * <td>Cp1145</td>
- * <td>IBM01145</td>
- * <td>CCSID01145 CP01145 ebcdic-es-284+euro </td>
- * </tr>
- * <tr>
- * <td>Cp1146</td>
- * <td>IBM01146</td>
- * <td>CCSID01146 CP01146 ebcdic-gb-285+euro </td>
- * </tr>
- * <tr>
- * <td>Cp1147</td>
- * <td>IBM01147</td>
- * <td>CCSID01147 CP01147 ebcdic-fr-297+euro </td>
- * </tr>
- * <tr>
- * <td>Cp1148</td>
- * <td>IBM01148</td>
- * <td>CCSID01148 CP01148 ebcdic-international-500+euro </td>
- * </tr>
- * <tr>
- * <td>Cp1149</td>
- * <td>IBM01149</td>
- * <td>CCSID01149 CP01149 ebcdic-is-871+euro </td>
- * </tr>
- * <tr>
- * <td>Cp1250</td>
- * <td>windows-1250</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1251</td>
- * <td>windows-1251</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1252</td>
- * <td>windows-1252</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1253</td>
- * <td>windows-1253</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1254</td>
- * <td>windows-1254</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1255</td>
- * <td>windows-1255</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1256</td>
- * <td>windows-1256</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1257</td>
- * <td>windows-1257</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1258</td>
- * <td>windows-1258</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1381</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp1383</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp273</td>
- * <td>IBM273</td>
- * <td>csIBM273 </td>
- * </tr>
- * <tr>
- * <td>Cp277</td>
- * <td>IBM277</td>
- * <td>EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 </td>
- * </tr>
- * <tr>
- * <td>Cp278</td>
- * <td>IBM278</td>
- * <td>CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 </td>
- * </tr>
- * <tr>
- * <td>Cp280</td>
- * <td>IBM280</td>
- * <td>ebcdic-cp-it csIBM280 </td>
- * </tr>
- * <tr>
- * <td>Cp284</td>
- * <td>IBM284</td>
- * <td>ebcdic-cp-es csIBM284 </td>
- * </tr>
- * <tr>
- * <td>Cp285</td>
- * <td>IBM285</td>
- * <td>ebcdic-cp-gb csIBM285 </td>
- * </tr>
- * <tr>
- * <td>Cp297</td>
- * <td>IBM297</td>
- * <td>ebcdic-cp-fr csIBM297 </td>
- * </tr>
- * <tr>
- * <td>Cp33722</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp420</td>
- * <td>IBM420</td>
- * <td>ebcdic-cp-ar1 csIBM420 </td>
- * </tr>
- * <tr>
- * <td>Cp424</td>
- * <td>IBM424</td>
- * <td>ebcdic-cp-he csIBM424 </td>
- * </tr>
- * <tr>
- * <td>Cp437</td>
- * <td>IBM437</td>
- * <td>437 csPC8CodePage437 </td>
- * </tr>
- * <tr>
- * <td>Cp500</td>
- * <td>IBM500</td>
- * <td>ebcdic-cp-be ebcdic-cp-ch csIBM500 </td>
- * </tr>
- * <tr>
- * <td>Cp737</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp775</td>
- * <td>IBM775</td>
- * <td>csPC775Baltic </td>
- * </tr>
- * <tr>
- * <td>Cp838</td>
- * <td>IBM-Thai</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp850</td>
- * <td>IBM850</td>
- * <td>850 csPC850Multilingual </td>
- * </tr>
- * <tr>
- * <td>Cp852</td>
- * <td>IBM852</td>
- * <td>852 csPCp852 </td>
- * </tr>
- * <tr>
- * <td>Cp855</td>
- * <td>IBM855</td>
- * <td>855 csIBM855 </td>
- * </tr>
- * <tr>
- * <td>Cp856</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp857</td>
- * <td>IBM857</td>
- * <td>857 csIBM857 </td>
- * </tr>
- * <tr>
- * <td>Cp858</td>
- * <td>IBM00858</td>
- * <td>CCSID00858 CP00858 PC-Multilingual-850+euro </td>
- * </tr>
- * <tr>
- * <td>Cp860</td>
- * <td>IBM860</td>
- * <td>860 csIBM860 </td>
- * </tr>
- * <tr>
- * <td>Cp861</td>
- * <td>IBM861</td>
- * <td>861 cp-is csIBM861 </td>
- * </tr>
- * <tr>
- * <td>Cp862</td>
- * <td>IBM862</td>
- * <td>862 csPC862LatinHebrew </td>
- * </tr>
- * <tr>
- * <td>Cp863</td>
- * <td>IBM863</td>
- * <td>863 csIBM863 </td>
- * </tr>
- * <tr>
- * <td>Cp864</td>
- * <td>IBM864</td>
- * <td>cp864 csIBM864 </td>
- * </tr>
- * <tr>
- * <td>Cp865</td>
- * <td>IBM865</td>
- * <td>865 csIBM865 </td>
- * </tr>
- * <tr>
- * <td>Cp866</td>
- * <td>IBM866</td>
- * <td>866 csIBM866 </td>
- * </tr>
- * <tr>
- * <td>Cp868</td>
- * <td>IBM868</td>
- * <td>cp-ar csIBM868 </td>
- * </tr>
- * <tr>
- * <td>Cp869</td>
- * <td>IBM869</td>
- * <td>cp-gr csIBM869 </td>
- * </tr>
- * <tr>
- * <td>Cp870</td>
- * <td>IBM870</td>
- * <td>ebcdic-cp-roece ebcdic-cp-yu csIBM870 </td>
- * </tr>
- * <tr>
- * <td>Cp871</td>
- * <td>IBM871</td>
- * <td>ebcdic-cp-is csIBM871 </td>
- * </tr>
- * <tr>
- * <td>Cp875</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp918</td>
- * <td>IBM918</td>
- * <td>ebcdic-cp-ar2 csIBM918 </td>
- * </tr>
- * <tr>
- * <td>Cp921</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp922</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp930</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp933</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp935</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp937</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp939</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp942</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp942C</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp943</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp943C</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp948</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp949</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp949C</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp950</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp964</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>Cp970</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>EUC_CN</td>
- * <td>GB2312</td>
- * <td>x-EUC-CN csGB2312 euccn euc-cn gb2312-80 gb2312-1980 CN-GB CN-GB-ISOIR165 </td>
- * </tr>
- * <tr>
- * <td>EUC_JP</td>
- * <td>EUC-JP</td>
- * <td>csEUCPkdFmtJapanese Extended_UNIX_Code_Packed_Format_for_Japanese eucjis x-eucjp eucjp x-euc-jp </td>
- * </tr>
- * <tr>
- * <td>EUC_JP_LINUX</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>EUC_JP_Solaris</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>EUC_KR</td>
- * <td>EUC-KR</td>
- * <td>csEUCKR ksc5601 5601 ksc5601_1987 ksc_5601 ksc5601-1987 ks_c_5601-1987 euckr </td>
- * </tr>
- * <tr>
- * <td>EUC_TW</td>
- * <td>EUC-TW</td>
- * <td>x-EUC-TW cns11643 euctw </td>
- * </tr>
- * <tr>
- * <td>GB18030</td>
- * <td>GB18030</td>
- * <td>gb18030-2000 </td>
- * </tr>
- * <tr>
- * <td>GBK</td>
- * <td>windows-936</td>
- * <td>CP936 MS936 ms_936 x-mswin-936 </td>
- * </tr>
- * <tr>
- * <td>ISCII91</td>
- * <td>?</td>
- * <td>x-ISCII91 iscii </td>
- * </tr>
- * <tr>
- * <td>ISO2022CN</td>
- * <td>ISO-2022-CN</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>ISO2022JP</td>
- * <td>ISO-2022-JP</td>
- * <td>csISO2022JP JIS jis_encoding csjisencoding </td>
- * </tr>
- * <tr>
- * <td>ISO2022KR</td>
- * <td>ISO-2022-KR</td>
- * <td>csISO2022KR </td>
- * </tr>
- * <tr>
- * <td>ISO2022_CN_CNS</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>ISO2022_CN_GB</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>ISO8859_1</td>
- * <td>ISO-8859-1</td>
- * <td>ISO_8859-1:1987 iso-ir-100 ISO_8859-1 latin1 l1 IBM819 CP819 csISOLatin1 8859_1 819 IBM-819 ISO8859-1 ISO_8859_1 </td>
- * </tr>
- * <tr>
- * <td>ISO8859_13</td>
- * <td>ISO-8859-13</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>ISO8859_15</td>
- * <td>ISO-8859-15</td>
- * <td>ISO_8859-15 Latin-9 8859_15 csISOlatin9 IBM923 cp923 923 L9 IBM-923 ISO8859-15 LATIN9 LATIN0 csISOlatin0 ISO8859_15_FDIS </td>
- * </tr>
- * <tr>
- * <td>ISO8859_2</td>
- * <td>ISO-8859-2</td>
- * <td>ISO_8859-2:1987 iso-ir-101 ISO_8859-2 latin2 l2 csISOLatin2 8859_2 iso8859_2 </td>
- * </tr>
- * <tr>
- * <td>ISO8859_3</td>
- * <td>ISO-8859-3</td>
- * <td>ISO_8859-3:1988 iso-ir-109 ISO_8859-3 latin3 l3 csISOLatin3 8859_3 </td>
- * </tr>
- * <tr>
- * <td>ISO8859_4</td>
- * <td>ISO-8859-4</td>
- * <td>ISO_8859-4:1988 iso-ir-110 ISO_8859-4 latin4 l4 csISOLatin4 8859_4 </td>
- * </tr>
- * <tr>
- * <td>ISO8859_5</td>
- * <td>ISO-8859-5</td>
- * <td>ISO_8859-5:1988 iso-ir-144 ISO_8859-5 cyrillic csISOLatinCyrillic 8859_5 </td>
- * </tr>
- * <tr>
- * <td>ISO8859_6</td>
- * <td>ISO-8859-6</td>
- * <td>ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ECMA-114 ASMO-708 arabic csISOLatinArabic 8859_6 </td>
- * </tr>
- * <tr>
- * <td>ISO8859_7</td>
- * <td>ISO-8859-7</td>
- * <td>ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ELOT_928 ECMA-118 greek greek8 csISOLatinGreek 8859_7 sun_eu_greek </td>
- * </tr>
- * <tr>
- * <td>ISO8859_8</td>
- * <td>ISO-8859-8</td>
- * <td>ISO_8859-8:1988 iso-ir-138 ISO_8859-8 hebrew csISOLatinHebrew 8859_8 </td>
- * </tr>
- * <tr>
- * <td>ISO8859_9</td>
- * <td>ISO-8859-9</td>
- * <td>ISO_8859-9:1989 iso-ir-148 ISO_8859-9 latin5 l5 csISOLatin5 8859_9 </td>
- * </tr>
- * <tr>
- * <td>JISAutoDetect</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>JIS_C6626-1983</td>
- * <td>JIS_C6626-1983</td>
- * <td>x-JIS0208 JIS0208 csISO87JISX0208 x0208 JIS_X0208-1983 iso-ir-87 </td>
- * </tr>
- * <tr>
- * <td>JIS_X0201</td>
- * <td>JIS_X0201</td>
- * <td>X0201 JIS0201 csHalfWidthKatakana </td>
- * </tr>
- * <tr>
- * <td>JIS_X0212-1990</td>
- * <td>JIS_X0212-1990</td>
- * <td>iso-ir-159 x0212 JIS0212 csISO159JISX02121990 </td>
- * </tr>
- * <tr>
- * <td>KOI8_R</td>
- * <td>KOI8-R</td>
- * <td>csKOI8R koi8 </td>
- * </tr>
- * <tr>
- * <td>MS874</td>
- * <td>windows-874</td>
- * <td>cp874 </td>
- * </tr>
- * <tr>
- * <td>MS932</td>
- * <td>Windows-31J</td>
- * <td>windows-932 csWindows31J x-ms-cp932 </td>
- * </tr>
- * <tr>
- * <td>MS949</td>
- * <td>windows-949</td>
- * <td>windows949 ms_949 x-windows-949 </td>
- * </tr>
- * <tr>
- * <td>MS950</td>
- * <td>windows-950</td>
- * <td>x-windows-950 </td>
- * </tr>
- * <tr>
- * <td>MS950_HKSCS</td>
- * <td></td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>MacArabic</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>MacCentralEurope</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>MacCroatian</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>MacCyrillic</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>MacDingbat</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>MacGreek</td>
- * <td>MacGreek</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>MacHebrew</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>MacIceland</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>MacRoman</td>
- * <td>MacRoman</td>
- * <td>Macintosh MAC csMacintosh </td>
- * </tr>
- * <tr>
- * <td>MacRomania</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>MacSymbol</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>MacThai</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>MacTurkish</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>MacUkraine</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>SJIS</td>
- * <td>Shift_JIS</td>
- * <td>MS_Kanji csShiftJIS shift-jis x-sjis pck </td>
- * </tr>
- * <tr>
- * <td>TIS620</td>
- * <td>TIS-620</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>UTF-16</td>
- * <td>UTF-16</td>
- * <td>UTF_16 </td>
- * </tr>
- * <tr>
- * <td>UTF8</td>
- * <td>UTF-8</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>UnicodeBig</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>UnicodeBigUnmarked</td>
- * <td>UTF-16BE</td>
- * <td>X-UTF-16BE UTF_16BE ISO-10646-UCS-2 </td>
- * </tr>
- * <tr>
- * <td>UnicodeLittle</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>UnicodeLittleUnmarked</td>
- * <td>UTF-16LE</td>
- * <td>UTF_16LE X-UTF-16LE </td>
- * </tr>
- * <tr>
- * <td>x-Johab</td>
- * <td>johab</td>
- * <td>johab cp1361 ms1361 ksc5601-1992 ksc5601_1992 </td>
- * </tr>
- * <tr>
- * <td>x-iso-8859-11</td>
- * <td>?</td>
- * <td></td>
- * </tr>
- * </table>
- *
- *
- * @version $Id: CharsetUtil.java,v 1.1 2004/10/25 07:26:46 ntherning Exp $
- */
-public class CharsetUtil {
- private static Log log = LogFactory.getLog(CharsetUtil.class);
-
- private static class Charset implements Comparable {
- private String canonical = null;
- private String mime = null;
- private String[] aliases = null;
-
- private Charset(String canonical, String mime, String[] aliases) {
- this.canonical = canonical;
- this.mime = mime;
- this.aliases = aliases;
- }
-
- public int compareTo(Object o) {
- Charset c = (Charset) o;
- return this.canonical.compareTo(c.canonical);
- }
- }
-
- private static Charset[] JAVA_CHARSETS = {
- new Charset("ISO8859_1", "ISO-8859-1",
- new String[] {"ISO_8859-1:1987", "iso-ir-100", "ISO_8859-1",
- "latin1", "l1", "IBM819", "CP819",
- "csISOLatin1", "8859_1", "819", "IBM-819",
- "ISO8859-1", "ISO_8859_1"}),
- new Charset("ISO8859_2", "ISO-8859-2",
- new String[] {"ISO_8859-2:1987", "iso-ir-101", "ISO_8859-2",
- "latin2", "l2", "csISOLatin2", "8859_2",
- "iso8859_2"}),
- new Charset("ISO8859_3", "ISO-8859-3", new String[] {"ISO_8859-3:1988", "iso-ir-109", "ISO_8859-3", "latin3", "l3", "csISOLatin3", "8859_3"}),
- new Charset("ISO8859_4", "ISO-8859-4",
- new String[] {"ISO_8859-4:1988", "iso-ir-110", "ISO_8859-4",
- "latin4", "l4", "csISOLatin4", "8859_4"}),
- new Charset("ISO8859_5", "ISO-8859-5",
- new String[] {"ISO_8859-5:1988", "iso-ir-144", "ISO_8859-5",
- "cyrillic", "csISOLatinCyrillic", "8859_5"}),
- new Charset("ISO8859_6", "ISO-8859-6", new String[] {"ISO_8859-6:1987", "iso-ir-127", "ISO_8859-6", "ECMA-114", "ASMO-708", "arabic", "csISOLatinArabic", "8859_6"}),
- new Charset("ISO8859_7", "ISO-8859-7",
- new String[] {"ISO_8859-7:1987", "iso-ir-126", "ISO_8859-7",
- "ELOT_928", "ECMA-118", "greek", "greek8",
- "csISOLatinGreek", "8859_7", "sun_eu_greek"}),
- new Charset("ISO8859_8", "ISO-8859-8", new String[] {"ISO_8859-8:1988", "iso-ir-138", "ISO_8859-8", "hebrew", "csISOLatinHebrew", "8859_8"}),
- new Charset("ISO8859_9", "ISO-8859-9",
- new String[] {"ISO_8859-9:1989", "iso-ir-148", "ISO_8859-9",
- "latin5", "l5", "csISOLatin5", "8859_9"}),
-
- new Charset("ISO8859_13", "ISO-8859-13", new String[] {}),
- new Charset("ISO8859_15", "ISO-8859-15",
- new String[] {"ISO_8859-15", "Latin-9", "8859_15",
- "csISOlatin9", "IBM923", "cp923", "923", "L9",
- "IBM-923", "ISO8859-15", "LATIN9", "LATIN0",
- "csISOlatin0", "ISO8859_15_FDIS"}),
- new Charset("KOI8_R", "KOI8-R", new String[] {"csKOI8R", "koi8"}),
- new Charset("ASCII", "US-ASCII",
- new String[] {"ANSI_X3.4-1968", "iso-ir-6",
- "ANSI_X3.4-1986", "ISO_646.irv:1991",
- "ISO646-US", "us", "IBM367", "cp367",
- "csASCII", "ascii7", "646", "iso_646.irv:1983"}),
- new Charset("UTF8", "UTF-8", new String[] {}),
- new Charset("UTF-16", "UTF-16", new String[] {"UTF_16"}),
- new Charset("UnicodeBigUnmarked", "UTF-16BE", new String[] {"X-UTF-16BE", "UTF_16BE", "ISO-10646-UCS-2"}),
- new Charset("UnicodeLittleUnmarked", "UTF-16LE", new String[] {"UTF_16LE", "X-UTF-16LE"}),
- new Charset("Big5", "Big5", new String[] {"csBig5", "CN-Big5", "BIG-FIVE", "BIGFIVE"}),
- new Charset("Big5_HKSCS", "Big5-HKSCS", new String[] {"big5hkscs"}),
- new Charset("EUC_JP", "EUC-JP",
- new String[] {"csEUCPkdFmtJapanese",
- "Extended_UNIX_Code_Packed_Format_for_Japanese",
- "eucjis", "x-eucjp", "eucjp", "x-euc-jp"}),
- new Charset("EUC_KR", "EUC-KR",
- new String[] {"csEUCKR", "ksc5601", "5601", "ksc5601_1987",
- "ksc_5601", "ksc5601-1987", "ks_c_5601-1987",
- "euckr"}),
- new Charset("GB18030", "GB18030", new String[] {"gb18030-2000"}),
- new Charset("EUC_CN", "GB2312", new String[] {"x-EUC-CN", "csGB2312", "euccn", "euc-cn", "gb2312-80", "gb2312-1980", "CN-GB", "CN-GB-ISOIR165"}),
- new Charset("GBK", "windows-936", new String[] {"CP936", "MS936", "ms_936", "x-mswin-936"}),
-
- new Charset("Cp037", "IBM037", new String[] {"ebcdic-cp-us", "ebcdic-cp-ca", "ebcdic-cp-wt", "ebcdic-cp-nl", "csIBM037"}),
- new Charset("Cp273", "IBM273", new String[] {"csIBM273"}),
- new Charset("Cp277", "IBM277", new String[] {"EBCDIC-CP-DK", "EBCDIC-CP-NO", "csIBM277"}),
- new Charset("Cp278", "IBM278", new String[] {"CP278", "ebcdic-cp-fi", "ebcdic-cp-se", "csIBM278"}),
- new Charset("Cp280", "IBM280", new String[] {"ebcdic-cp-it", "csIBM280"}),
- new Charset("Cp284", "IBM284", new String[] {"ebcdic-cp-es", "csIBM284"}),
- new Charset("Cp285", "IBM285", new String[] {"ebcdic-cp-gb", "csIBM285"}),
- new Charset("Cp297", "IBM297", new String[] {"ebcdic-cp-fr", "csIBM297"}),
- new Charset("Cp420", "IBM420", new String[] {"ebcdic-cp-ar1", "csIBM420"}),
- new Charset("Cp424", "IBM424", new String[] {"ebcdic-cp-he", "csIBM424"}),
- new Charset("Cp437", "IBM437", new String[] {"437", "csPC8CodePage437"}),
- new Charset("Cp500", "IBM500", new String[] {"ebcdic-cp-be", "ebcdic-cp-ch", "csIBM500"}),
- new Charset("Cp775", "IBM775", new String[] {"csPC775Baltic"}),
- new Charset("Cp838", "IBM-Thai", new String[] {}),
- new Charset("Cp850", "IBM850", new String[] {"850", "csPC850Multilingual"}),
- new Charset("Cp852", "IBM852", new String[] {"852", "csPCp852"}),
- new Charset("Cp855", "IBM855", new String[] {"855", "csIBM855"}),
- new Charset("Cp857", "IBM857", new String[] {"857", "csIBM857"}),
- new Charset("Cp858", "IBM00858",
- new String[] {"CCSID00858", "CP00858",
- "PC-Multilingual-850+euro"}),
- new Charset("Cp860", "IBM860", new String[] {"860", "csIBM860"}),
- new Charset("Cp861", "IBM861", new String[] {"861", "cp-is", "csIBM861"}),
- new Charset("Cp862", "IBM862", new String[] {"862", "csPC862LatinHebrew"}),
- new Charset("Cp863", "IBM863", new String[] {"863", "csIBM863"}),
- new Charset("Cp864", "IBM864", new String[] {"cp864", "csIBM864"}),
- new Charset("Cp865", "IBM865", new String[] {"865", "csIBM865"}),
- new Charset("Cp866", "IBM866", new String[] {"866", "csIBM866"}),
- new Charset("Cp868", "IBM868", new String[] {"cp-ar", "csIBM868"}),
- new Charset("Cp869", "IBM869", new String[] {"cp-gr", "csIBM869"}),
- new Charset("Cp870", "IBM870", new String[] {"ebcdic-cp-roece", "ebcdic-cp-yu", "csIBM870"}),
- new Charset("Cp871", "IBM871", new String[] {"ebcdic-cp-is", "csIBM871"}),
- new Charset("Cp918", "IBM918", new String[] {"ebcdic-cp-ar2", "csIBM918"}),
- new Charset("Cp1026", "IBM1026", new String[] {"csIBM1026"}),
- new Charset("Cp1047", "IBM1047", new String[] {"IBM-1047"}),
- new Charset("Cp1140", "IBM01140",
- new String[] {"CCSID01140", "CP01140",
- "ebcdic-us-37+euro"}),
- new Charset("Cp1141", "IBM01141",
- new String[] {"CCSID01141", "CP01141",
- "ebcdic-de-273+euro"}),
- new Charset("Cp1142", "IBM01142", new String[] {"CCSID01142", "CP01142", "ebcdic-dk-277+euro", "ebcdic-no-277+euro"}),
- new Charset("Cp1143", "IBM01143", new String[] {"CCSID01143", "CP01143", "ebcdic-fi-278+euro", "ebcdic-se-278+euro"}),
- new Charset("Cp1144", "IBM01144", new String[] {"CCSID01144", "CP01144", "ebcdic-it-280+euro"}),
- new Charset("Cp1145", "IBM01145", new String[] {"CCSID01145", "CP01145", "ebcdic-es-284+euro"}),
- new Charset("Cp1146", "IBM01146", new String[] {"CCSID01146", "CP01146", "ebcdic-gb-285+euro"}),
- new Charset("Cp1147", "IBM01147", new String[] {"CCSID01147", "CP01147", "ebcdic-fr-297+euro"}),
- new Charset("Cp1148", "IBM01148", new String[] {"CCSID01148", "CP01148", "ebcdic-international-500+euro"}),
- new Charset("Cp1149", "IBM01149", new String[] {"CCSID01149", "CP01149", "ebcdic-is-871+euro"}),
- new Charset("Cp1250", "windows-1250", new String[] {}),
- new Charset("Cp1251", "windows-1251", new String[] {}),
- new Charset("Cp1252", "windows-1252", new String[] {}),
- new Charset("Cp1253", "windows-1253", new String[] {}),
- new Charset("Cp1254", "windows-1254", new String[] {}),
- new Charset("Cp1255", "windows-1255", new String[] {}),
- new Charset("Cp1256", "windows-1256", new String[] {}),
- new Charset("Cp1257", "windows-1257", new String[] {}),
- new Charset("Cp1258", "windows-1258", new String[] {}),
- new Charset("ISO2022CN", "ISO-2022-CN", new String[] {}),
- new Charset("ISO2022JP", "ISO-2022-JP", new String[] {"csISO2022JP", "JIS", "jis_encoding", "csjisencoding"}),
- new Charset("ISO2022KR", "ISO-2022-KR", new String[] {"csISO2022KR"}),
- new Charset("JIS_X0201", "JIS_X0201", new String[] {"X0201", "JIS0201", "csHalfWidthKatakana"}),
- new Charset("JIS_X0212-1990", "JIS_X0212-1990", new String[] {"iso-ir-159", "x0212", "JIS0212", "csISO159JISX02121990"}),
- new Charset("JIS_C6626-1983", "JIS_C6626-1983", new String[] {"x-JIS0208", "JIS0208", "csISO87JISX0208", "x0208", "JIS_X0208-1983", "iso-ir-87"}),
- new Charset("SJIS", "Shift_JIS", new String[] {"MS_Kanji", "csShiftJIS", "shift-jis", "x-sjis", "pck"}),
- new Charset("TIS620", "TIS-620", new String[] {}),
- new Charset("MS932", "Windows-31J", new String[] {"windows-932", "csWindows31J", "x-ms-cp932"}),
- new Charset("EUC_TW", "EUC-TW", new String[] {"x-EUC-TW", "cns11643", "euctw"}),
- new Charset("x-Johab", "johab", new String[] {"johab", "cp1361", "ms1361", "ksc5601-1992", "ksc5601_1992"}),
- new Charset("MS950_HKSCS", "", new String[] {}),
- new Charset("MS874", "windows-874", new String[] {"cp874"}),
- new Charset("MS949", "windows-949", new String[] {"windows949", "ms_949", "x-windows-949"}),
- new Charset("MS950", "windows-950", new String[] {"x-windows-950"}),
-
- new Charset("Cp737", null, new String[] {}),
- new Charset("Cp856", null, new String[] {}),
- new Charset("Cp875", null, new String[] {}),
- new Charset("Cp921", null, new String[] {}),
- new Charset("Cp922", null, new String[] {}),
- new Charset("Cp930", null, new String[] {}),
- new Charset("Cp933", null, new String[] {}),
- new Charset("Cp935", null, new String[] {}),
- new Charset("Cp937", null, new String[] {}),
- new Charset("Cp939", null, new String[] {}),
- new Charset("Cp942", null, new String[] {}),
- new Charset("Cp942C", null, new String[] {}),
- new Charset("Cp943", null, new String[] {}),
- new Charset("Cp943C", null, new String[] {}),
- new Charset("Cp948", null, new String[] {}),
- new Charset("Cp949", null, new String[] {}),
- new Charset("Cp949C", null, new String[] {}),
- new Charset("Cp950", null, new String[] {}),
- new Charset("Cp964", null, new String[] {}),
- new Charset("Cp970", null, new String[] {}),
- new Charset("Cp1006", null, new String[] {}),
- new Charset("Cp1025", null, new String[] {}),
- new Charset("Cp1046", null, new String[] {}),
- new Charset("Cp1097", null, new String[] {}),
- new Charset("Cp1098", null, new String[] {}),
- new Charset("Cp1112", null, new String[] {}),
- new Charset("Cp1122", null, new String[] {}),
- new Charset("Cp1123", null, new String[] {}),
- new Charset("Cp1124", null, new String[] {}),
- new Charset("Cp1381", null, new String[] {}),
- new Charset("Cp1383", null, new String[] {}),
- new Charset("Cp33722", null, new String[] {}),
- new Charset("Big5_Solaris", null, new String[] {}),
- new Charset("EUC_JP_LINUX", null, new String[] {}),
- new Charset("EUC_JP_Solaris", null, new String[] {}),
- new Charset("ISCII91", null, new String[] {"x-ISCII91", "iscii"}),
- new Charset("ISO2022_CN_CNS", null, new String[] {}),
- new Charset("ISO2022_CN_GB", null, new String[] {}),
- new Charset("x-iso-8859-11", null, new String[] {}),
- new Charset("JISAutoDetect", null, new String[] {}),
- new Charset("MacArabic", null, new String[] {}),
- new Charset("MacCentralEurope", null, new String[] {}),
- new Charset("MacCroatian", null, new String[] {}),
- new Charset("MacCyrillic", null, new String[] {}),
- new Charset("MacDingbat", null, new String[] {}),
- new Charset("MacGreek", "MacGreek", new String[] {}),
- new Charset("MacHebrew", null, new String[] {}),
- new Charset("MacIceland", null, new String[] {}),
- new Charset("MacRoman", "MacRoman", new String[] {"Macintosh", "MAC", "csMacintosh"}),
- new Charset("MacRomania", null, new String[] {}),
- new Charset("MacSymbol", null, new String[] {}),
- new Charset("MacThai", null, new String[] {}),
- new Charset("MacTurkish", null, new String[] {}),
- new Charset("MacUkraine", null, new String[] {}),
- new Charset("UnicodeBig", null, new String[] {}),
- new Charset("UnicodeLittle", null, new String[] {})
- };
-
- /**
- * Contains the canonical names of character sets which can be used to
- * decode bytes into Java chars.
- */
- private static TreeSet decodingSupported = null;
-
- /**
- * Contains the canonical names of character sets which can be used to
- * encode Java chars into bytes.
- */
- private static TreeSet encodingSupported = null;
-
- /**
- * Maps character set names to Charset objects. All possible names of
- * a charset will be mapped to the Charset.
- */
- private static HashMap charsetMap = null;
-
- static {
- decodingSupported = new TreeSet();
- encodingSupported = new TreeSet();
- byte[] dummy = new byte[] {'d', 'u', 'm', 'm', 'y'};
- for (int i = 0; i < JAVA_CHARSETS.length; i++) {
- try {
- String s = new String(dummy, JAVA_CHARSETS[i].canonical);
- decodingSupported.add(JAVA_CHARSETS[i].canonical.toLowerCase());
- } catch (UnsupportedOperationException e) {
- } catch (UnsupportedEncodingException e) {
- }
- try {
- "dummy".getBytes(JAVA_CHARSETS[i].canonical);
- encodingSupported.add(JAVA_CHARSETS[i].canonical.toLowerCase());
- } catch (UnsupportedOperationException e) {
- } catch (UnsupportedEncodingException e) {
- }
- }
-
- charsetMap = new HashMap();
- for (int i = 0; i < JAVA_CHARSETS.length; i++) {
- Charset c = JAVA_CHARSETS[i];
- charsetMap.put(c.canonical.toLowerCase(), c);
- if (c.mime != null) {
- charsetMap.put(c.mime.toLowerCase(), c);
- }
- if (c.aliases != null) {
- for (int j = 0; j < c.aliases.length; j++) {
- charsetMap.put(c.aliases[j].toLowerCase(), c);
- }
- }
- }
-
- if (log.isDebugEnabled()) {
- log.debug("Character sets which support decoding: "
- + decodingSupported);
- log.debug("Character sets which support encoding: "
- + encodingSupported);
- }
- }
-
- /**
- * Determines if the VM supports encoding (chars to bytes) the
- * specified character set. NOTE: the given character set name may
- * not be known to the VM even if this method returns <code>true</code>.
- * Use {@link #toJavaCharset(String)} to get the canonical Java character
- * set name.
- *
- * @param charsetName the characters set name.
- * @return <code>true</code> if encoding is supported, <code>false</code>
- * otherwise.
- */
- public static boolean isEncodingSupported(String charsetName) {
- return encodingSupported.contains(charsetName.toLowerCase());
- }
-
- /**
- * Determines if the VM supports decoding (bytes to chars) the
- * specified character set. NOTE: the given character set name may
- * not be known to the VM even if this method returns <code>true</code>.
- * Use {@link #toJavaCharset(String)} to get the canonical Java character
- * set name.
- *
- * @param charsetName the characters set name.
- * @return <code>true</code> if decoding is supported, <code>false</code>
- * otherwise.
- */
- public static boolean isDecodingSupported(String charsetName) {
- return decodingSupported.contains(charsetName.toLowerCase());
- }
-
- /**
- * Gets the preferred MIME character set name for the specified
- * character set or <code>null</code> if not known.
- *
- * @param charsetName the character set name to look for.
- * @return the MIME preferred name or <code>null</code> if not known.
- */
- public static String toMimeCharset(String charsetName) {
- Charset c = (Charset) charsetMap.get(charsetName.toLowerCase());
- if (c != null) {
- return c.mime;
- }
- return null;
- }
-
- /**
- * Gets the canonical Java character set name for the specified
- * character set or <code>null</code> if not known. This should be
- * called before doing any conversions using the Java API. NOTE:
- * you must use {@link #isEncodingSupported(String)} or
- * {@link #isDecodingSupported(String)} to make sure the returned
- * Java character set is supported by the current VM.
- *
- * @param charsetName the character set name to look for.
- * @return the canonical Java name or <code>null</code> if not known.
- */
- public static String toJavaCharset(String charsetName) {
- Charset c = (Charset) charsetMap.get(charsetName.toLowerCase());
- if (c != null) {
- return c.canonical;
- }
- return null;
- }
-
- public static java.nio.charset.Charset getCharset(String charsetName) {
- String defaultCharset = "ISO-8859-1";
-
- // Use the default chareset if given charset is null
- if(charsetName == null) charsetName = defaultCharset;
-
- try {
- return java.nio.charset.Charset.forName(charsetName);
- } catch (IllegalCharsetNameException e) {
- log.info("Illegal charset " + charsetName + ", fallback to " + defaultCharset + ": " + e);
- // Use default charset on exception
- return java.nio.charset.Charset.forName(defaultCharset);
- } catch (UnsupportedCharsetException ex) {
- log.info("Unsupported charset " + charsetName + ", fallback to " + defaultCharset + ": " + ex);
- // Use default charset on exception
- return java.nio.charset.Charset.forName(defaultCharset);
- }
-
- }
- /*
- * Uncomment the code below and run the main method to regenerate the
- * Javadoc table above when the known charsets change.
- */
-
- /*
- private static String dumpHtmlTable() {
- LinkedList l = new LinkedList(Arrays.asList(JAVA_CHARSETS));
- Collections.sort(l);
- StringBuffer sb = new StringBuffer();
- sb.append(" * <table>\n");
- sb.append(" * <tr>\n");
- sb.append(" * <td>Canonical (Java) name</td>\n");
- sb.append(" * <td>MIME preferred</td>\n");
- sb.append(" * <td>Aliases</td>\n");
- sb.append(" * </tr>\n");
-
- for (Iterator it = l.iterator(); it.hasNext();) {
- Charset c = (Charset) it.next();
- sb.append(" * <tr>\n");
- sb.append(" * <td>" + c.canonical + "</td>\n");
- sb.append(" * <td>" + (c.mime == null ? "?" : c.mime)+ "</td>\n");
- sb.append(" * <td>");
- for (int i = 0; c.aliases != null && i < c.aliases.length; i++) {
- sb.append(c.aliases[i] + " ");
- }
- sb.append("</td>\n");
- sb.append(" * </tr>\n");
- }
- sb.append(" * </table>\n");
- return sb.toString();
- }
-
- public static void main(String[] args) {
- System.out.println(dumpHtmlTable());
- }*/
-}
diff --git a/src/org/apache/james/mime4j/util/PartialInputStream.java b/src/org/apache/james/mime4j/util/PartialInputStream.java
deleted file mode 100644
index a5ac0596d..000000000
--- a/src/org/apache/james/mime4j/util/PartialInputStream.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-
-package org.apache.james.mime4j.util;
-
-import java.io.InputStream;
-import java.io.IOException;
-
-public class PartialInputStream extends PositionInputStream {
- private final long limit;
-
- public PartialInputStream(InputStream inputStream, long offset, long length) throws IOException {
- super(inputStream);
- inputStream.skip(offset);
- this.limit = offset + length;
- }
-
- public int available() throws IOException {
- return Math.min(super.available(), getBytesLeft());
- }
-
- public int read() throws IOException {
- if (limit > position)
- return super.read();
- else
- return -1;
- }
-
- public int read(byte b[]) throws IOException {
- return read(b, 0, b.length);
- }
-
- public int read(byte b[], int off, int len) throws IOException {
- len = Math.min(len, getBytesLeft());
- return super.read(b, off, len); //To change body of overridden methods use File | Settings | File Templates.
- }
-
- public long skip(long n) throws IOException {
- n = Math.min(n, getBytesLeft());
- return super.skip(n); //To change body of overridden methods use File | Settings | File Templates.
- }
-
- private int getBytesLeft() {
- return (int)Math.min(Integer.MAX_VALUE, limit - position);
- }
-}
diff --git a/src/org/apache/james/mime4j/util/PositionInputStream.java b/src/org/apache/james/mime4j/util/PositionInputStream.java
deleted file mode 100644
index 9fcd21d0c..000000000
--- a/src/org/apache/james/mime4j/util/PositionInputStream.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-
-package org.apache.james.mime4j.util;
-
-import java.io.InputStream;
-import java.io.IOException;
-
-public class PositionInputStream extends InputStream {
-
- private final InputStream inputStream;
- protected long position = 0;
- private long markedPosition = 0;
-
- public PositionInputStream(InputStream inputStream) {
- this.inputStream = inputStream;
- }
-
- public long getPosition() {
- return position;
- }
-
- public int available() throws IOException {
- return inputStream.available();
- }
-
- public int read() throws IOException {
- int b = inputStream.read();
- if (b != -1)
- position++;
- return b;
- }
-
- public void close() throws IOException {
- inputStream.close();
- }
-
- public void reset() throws IOException {
- inputStream.reset();
- position = markedPosition;
- }
-
- public boolean markSupported() {
- return inputStream.markSupported();
- }
-
- public void mark(int readlimit) {
- inputStream.mark(readlimit);
- markedPosition = position;
- }
-
- public long skip(long n) throws IOException {
- final long c = inputStream.skip(n);
- position += c;
- return c;
- }
-
- public int read(byte b[]) throws IOException {
- final int c = inputStream.read(b);
- position += c;
- return c;
- }
-
- public int read(byte b[], int off, int len) throws IOException {
- final int c = inputStream.read(b, off, len);
- position += c;
- return c;
- }
-
-}
diff --git a/src/org/apache/james/mime4j/util/SimpleTempStorage.java b/src/org/apache/james/mime4j/util/SimpleTempStorage.java
deleted file mode 100644
index 7ca0371a2..000000000
--- a/src/org/apache/james/mime4j/util/SimpleTempStorage.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.util;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Random;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- *
- * @version $Id: SimpleTempStorage.java,v 1.2 2004/10/02 12:41:11 ntherning Exp $
- */
-public class SimpleTempStorage extends TempStorage {
- private static Log log = LogFactory.getLog(SimpleTempStorage.class);
-
- private TempPath rootPath = null;
- private Random random = new Random();
-
- /**
- * Creates a new <code>SimpleTempStorageManager</code> instance.
- */
- public SimpleTempStorage() {
- rootPath = new SimpleTempPath(System.getProperty("java.io.tmpdir"));
- }
-
- private TempPath createTempPath(TempPath parent, String prefix)
- throws IOException {
-
- if (prefix == null) {
- prefix = "";
- }
-
- File p = null;
- int count = 1000;
- do {
- long n = Math.abs(random.nextLong());
- p = new File(parent.getAbsolutePath(), prefix + n);
- count--;
- } while (p.exists() && count > 0);
-
- if (p.exists() || !p.mkdirs()) {
- log.error("Unable to mkdirs on " + p.getAbsolutePath());
- throw new IOException("Creating dir '"
- + p.getAbsolutePath() + "' failed.");
- }
-
- return new SimpleTempPath(p);
- }
-
- private TempFile createTempFile(TempPath parent, String prefix,
- String suffix) throws IOException {
-
- if (prefix == null) {
- prefix = "";
- }
- if (suffix == null) {
- suffix = ".tmp";
- }
-
- File f = null;
-
- int count = 1000;
- synchronized (this) {
- do {
- long n = Math.abs(random.nextLong());
- f = new File(parent.getAbsolutePath(), prefix + n + suffix);
- count--;
- } while (f.exists() && count > 0);
-
- if (f.exists()) {
- throw new IOException("Creating temp file failed: "
- + "Unable to find unique file name");
- }
-
- try {
- f.createNewFile();
- } catch (IOException e) {
- throw new IOException("Creating dir '"
- + f.getAbsolutePath() + "' failed.");
- }
- }
-
- return new SimpleTempFile(f);
- }
-
- /**
- * @see org.apache.james.mime4j.util.TempStorage#getRootTempPath()
- */
- public TempPath getRootTempPath() {
- return rootPath;
- }
-
- private class SimpleTempPath implements TempPath {
- private File path = null;
-
- private SimpleTempPath(String path) {
- this.path = new File(path);
- }
-
- private SimpleTempPath(File path) {
- this.path = path;
- }
-
- /**
- * @see org.apache.james.mime4j.util.TempPath#createTempFile()
- */
- public TempFile createTempFile() throws IOException {
- return SimpleTempStorage.this.createTempFile(this, null, null);
- }
-
- /**
- * @see org.apache.james.mime4j.util.TempPath#createTempFile(java.lang.String, java.lang.String)
- */
- public TempFile createTempFile(String prefix, String suffix)
- throws IOException {
-
- return SimpleTempStorage.this.createTempFile(this, prefix, suffix);
- }
-
- /**
- * @see org.apache.james.mime4j.util.TempPath#createTempFile(java.lang.String, java.lang.String, boolean)
- */
- public TempFile createTempFile(String prefix, String suffix,
- boolean allowInMemory)
- throws IOException {
-
- return SimpleTempStorage.this.createTempFile(this, prefix, suffix);
- }
-
- /**
- * @see org.apache.james.mime4j.util.TempPath#getAbsolutePath()
- */
- public String getAbsolutePath() {
- return path.getAbsolutePath();
- }
-
- /**
- * Do nothing
- */
- public void delete() {
- }
-
- /**
- * @see org.apache.james.mime4j.util.TempPath#createTempPath()
- */
- public TempPath createTempPath() throws IOException {
- return SimpleTempStorage.this.createTempPath(this, null);
- }
-
- /**
- * @see org.apache.james.mime4j.util.TempPath#createTempPath(java.lang.String)
- */
- public TempPath createTempPath(String prefix) throws IOException {
- return SimpleTempStorage.this.createTempPath(this, prefix);
- }
-
- }
-
- private class SimpleTempFile implements TempFile {
- private File file = null;
-
- private SimpleTempFile(File file) {
- this.file = file;
- this.file.deleteOnExit();
- }
-
- /**
- * @see org.apache.james.mime4j.util.TempFile#getInputStream()
- */
- public InputStream getInputStream() throws IOException {
- return new BufferedInputStream(new FileInputStream(file));
- }
-
- /**
- * @see org.apache.james.mime4j.util.TempFile#getOutputStream()
- */
- public OutputStream getOutputStream() throws IOException {
- return new BufferedOutputStream(new FileOutputStream(file));
- }
-
- /**
- * @see org.apache.james.mime4j.util.TempFile#getAbsolutePath()
- */
- public String getAbsolutePath() {
- return file.getAbsolutePath();
- }
-
- /**
- * Do nothing
- */
- public void delete() {
- // Not implementated
- }
-
- /**
- * @see org.apache.james.mime4j.util.TempFile#isInMemory()
- */
- public boolean isInMemory() {
- return false;
- }
-
- /**
- * @see org.apache.james.mime4j.util.TempFile#length()
- */
- public long length() {
- return file.length();
- }
-
- }
-}
diff --git a/src/org/apache/james/mime4j/util/TempFile.java b/src/org/apache/james/mime4j/util/TempFile.java
deleted file mode 100644
index f67e1e93e..000000000
--- a/src/org/apache/james/mime4j/util/TempFile.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * @version $Id: TempFile.java,v 1.3 2004/10/02 12:41:11 ntherning Exp $
- */
-public interface TempFile {
- /**
- * Gets an <code>InputStream</code> to read bytes from this temporary file.
- * NOTE: The stream should NOT be wrapped in
- * <code>BufferedInputStream</code> by the caller. If the implementing
- * <code>TempFile</code> creates a <code>FileInputStream</code> or any
- * other stream which would benefit from being buffered it's the
- * <code>TempFile</code>'s responsibility to wrap it.
- *
- * @return the stream.
- * @throws IOException
- */
- InputStream getInputStream() throws IOException;
-
- /**
- * Gets an <code>OutputStream</code> to write bytes to this temporary file.
- * NOTE: The stream should NOT be wrapped in
- * <code>BufferedOutputStream</code> by the caller. If the implementing
- * <code>TempFile</code> creates a <code>FileOutputStream</code> or any
- * other stream which would benefit from being buffered it's the
- * <code>TempFile</code>'s responsibility to wrap it.
- *
- * @return the stream.
- * @throws IOException
- */
- OutputStream getOutputStream() throws IOException;
-
- /**
- * Returns the absolute path including file name of this
- * <code>TempFile</code>. The path may be <code>null</code> if this is
- * an in-memory file.
- *
- * @return the absolute path.
- */
- String getAbsolutePath();
-
- /**
- * Deletes this file as soon as possible.
- */
- void delete();
-
- /**
- * Determines if this is an in-memory file.
- *
- * @return <code>true</code> if this file is currently in memory,
- * <code>false</code> otherwise.
- */
- boolean isInMemory();
-
- /**
- * Gets the length of this temporary file.
- *
- * @return the length.
- */
- long length();
-}
diff --git a/src/org/apache/james/mime4j/util/TempPath.java b/src/org/apache/james/mime4j/util/TempPath.java
deleted file mode 100644
index 3b55aa6db..000000000
--- a/src/org/apache/james/mime4j/util/TempPath.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.util;
-
-import java.io.IOException;
-
-/**
- *
- * @version $Id: TempPath.java,v 1.2 2004/10/02 12:41:11 ntherning Exp $
- */
-public interface TempPath {
- TempPath createTempPath() throws IOException;
- TempPath createTempPath(String prefix) throws IOException;
-
- /**
- * Creates a new temporary file. Wheter it will be be created in memory
- * or on disk is up to to the implementation.
- * The prefix will be empty and the suffix will be
- * <code>.tmp</code> if created on disk.
- *
- * @return the temporary file.
- */
- TempFile createTempFile() throws IOException;
-
- /**
- * Creates a new temporary file. Wheter it will be be created in memory
- * or on disk is up to to the implementation.
- * The prefix and suffix can be set by the user.
- *
- * @param prefix the prefix to use. <code>null</code> gives no prefix.
- * @param suffix the suffix to use. <code>null</code> gives
- * <code>.tmp</code>.
- * @return the temporary file.
- */
- TempFile createTempFile(String prefix, String suffix) throws IOException;
-
- /**
- * Creates a new temporary file. Wheter it will be be created in memory
- * or on disk can be specified using the <code>allowInMemory</code>
- * parameter. If the implementation doesn't support in-memory files
- * the new file will be created on disk.
- * The prefix and suffix can be set by the user.
- *
- * @param prefix the prefix to use. <code>null</code> gives no prefix.
- * @param suffix the suffix to use. <code>null</code> gives
- * <code>.tmp</code>.
- * @param allowInMemory if <code>true</code> the file MIGHT be created in
- * memory if supported by the implentation. If <code>false</code> the
- * file MUST be created on disk.
- * @return the temporary file.
- */
- TempFile createTempFile(String prefix, String suffix,
- boolean allowInMemory) throws IOException;
- String getAbsolutePath();
- void delete();
-}
diff --git a/src/org/apache/james/mime4j/util/TempStorage.java b/src/org/apache/james/mime4j/util/TempStorage.java
deleted file mode 100644
index ca951531a..000000000
--- a/src/org/apache/james/mime4j/util/TempStorage.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mime4j.util;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- *
- * @version $Id: TempStorage.java,v 1.2 2004/10/02 12:41:11 ntherning Exp $
- */
-public abstract class TempStorage {
- private static Log log = LogFactory.getLog(TempStorage.class);
- private static TempStorage inst = null;
-
- static {
-
- String clazz = System.getProperty("org.apache.james.mime4j.tempStorage");
- try {
-
- if (inst != null) {
- inst = (TempStorage) Class.forName(clazz).newInstance();
- }
-
- } catch (Throwable t) {
- log.warn("Unable to create or instantiate TempStorage class '"
- + clazz + "' using SimpleTempStorage instead", t);
- }
-
- if (inst == null) {
- inst = new SimpleTempStorage();
- }
- }
-
- /**
- * Gets the root temporary path which should be used to
- * create new temporary paths or files.
- *
- * @return the root temporary path.
- */
- public abstract TempPath getRootTempPath();
-
- public static TempStorage getInstance() {
- return inst;
- }
-
- public static void setInstance(TempStorage inst) {
- if (inst == null) {
- throw new NullPointerException("inst");
- }
- TempStorage.inst = inst;
- }
-}
diff --git a/tests/Android.mk b/tests/Android.mk
deleted file mode 100644
index c4e7fd425..000000000
--- a/tests/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2008, The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-# Notice that we don't have to include the src files of Email because, by
-# running the tests using an instrumentation targeting Eamil, we
-# automatically get all of its classes loaded into our environment.
-
-LOCAL_PACKAGE_NAME := EmailTests
-
-LOCAL_INSTRUMENTATION_FOR := Email
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
deleted file mode 100644
index 4657baa4a..000000000
--- a/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.email.tests">
-
- <!-- We add an application tag here just so that we can indicate that
- this package needs to link against the android.test library,
- which is needed when building test cases. -->
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
-
- <!--
- This declares that this app uses the instrumentation test runner targeting
- the package of com.android.email. To run the tests use the command:
- "adb shell am instrument -w com.android.email.tests/android.test.InstrumentationTestRunner"
- -->
- <instrumentation android:name="android.test.InstrumentationTestRunner"
- android:targetPackage="com.android.email"
- android:label="Tests for Email."/>
-
-</manifest>
diff --git a/tests/src/com/android/email/AccountUnitTests.java b/tests/src/com/android/email/AccountUnitTests.java
deleted file mode 100644
index 46ca501ef..000000000
--- a/tests/src/com/android/email/AccountUnitTests.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email;
-
-import android.content.SharedPreferences;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-/**
- * This is a series of unit tests for the Account class.
- *
- * Technically these are functional because they use the underlying preferences framework.
- */
-@SmallTest
-public class AccountUnitTests extends AndroidTestCase {
-
- private Preferences mPreferences;
-
- private String mUuid;
- private Account mAccount;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- mPreferences = Preferences.getPreferences(getContext());
- }
-
- /**
- * Delete any dummy accounts we set up for this test
- */
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
-
- if (mAccount != null && mPreferences != null) {
- mAccount.delete(mPreferences);
- }
- }
-
- /**
- * Test the update path from .transportUri to .senderUri
- */
- public void testTransportToSenderUpdate() {
-
- final String TEST_VALUE = "This Is The Sender Uri";
-
- // Create a dummy account
- createTestAccount();
-
- // Tweak it to look like an old account (with ".transportUri")
- SharedPreferences.Editor editor = mPreferences.mSharedPreferences.edit();
- editor.remove(mUuid + ".senderUri");
- editor.putString(mUuid + ".transportUri", Utility.base64Encode(TEST_VALUE));
- editor.commit();
-
- // Read it, see if we get back the string as a sender string
- mAccount.refresh(mPreferences);
- assertEquals(TEST_VALUE, mAccount.getSenderUri());
-
- // Update it - this will automatically convert it to the newer name
- mAccount.save(mPreferences);
-
- // Confirm that the field was replaced with the new form
- String newString = mPreferences.mSharedPreferences.getString(mUuid + ".senderUri", null);
- assertEquals(TEST_VALUE, Utility.base64Decode(newString));
- String oldString = mPreferences.mSharedPreferences.getString(mUuid + ".transportUri", null);
- assertNull(oldString);
-
- }
-
- /**
- * Test the update path for old IMAP accounts that didn't have DELETE_POLICY_ON_DELETE
- * properly preset.
- */
- public void testImapDeletePolicyUpdate() {
-
- final String STORE_URI_IMAP = "imap://user:pass@imap-server.com";
- final String STORE_URI_POP3 = "pop3://user:pass@pop3-server.com";
-
- // Test 1: try it with a POP3 account - no update should occur
-
- // create a dummy account
- createTestAccount();
-
- // set up a minimal POP3 account with default value
- SharedPreferences.Editor editor = mPreferences.mSharedPreferences.edit();
- editor.putString(mUuid + ".storeUri", Utility.base64Encode(STORE_URI_POP3));
- editor.putInt(mUuid + ".deletePolicy", Account.DELETE_POLICY_NEVER);
- editor.commit();
-
- // read it in and confirm that we get the default value
- mAccount.refresh(mPreferences);
- assertEquals(Account.DELETE_POLICY_NEVER, mAccount.getDeletePolicy());
-
- // flush it and confirm that we don't change the database
- mAccount.save(mPreferences);
- int storedPolicy = mPreferences.mSharedPreferences.getInt(mUuid + ".deletePolicy", -1);
- assertEquals(Account.DELETE_POLICY_NEVER, storedPolicy);
-
- // Test 2: try it with an IMAP account - this time we should see an auto-update
-
- // create a dummy account
- mAccount.delete(mPreferences);
- createTestAccount();
-
- // tweak it to have the wrong settings - this is what IMAP accounts look like
- // with manual setup, in earlier versions
- editor = mPreferences.mSharedPreferences.edit();
- editor.putString(mUuid + ".storeUri", Utility.base64Encode(STORE_URI_IMAP));
- editor.putInt(mUuid + ".deletePolicy", Account.DELETE_POLICY_NEVER);
- editor.commit();
-
- // Now read it in and confirm that we get the properly updated value
- mAccount.refresh(mPreferences);
- assertEquals(Account.DELETE_POLICY_ON_DELETE, mAccount.getDeletePolicy());
-
- // Now flush it and confirm that we fixed the database
- mAccount.save(mPreferences);
- storedPolicy = mPreferences.mSharedPreferences.getInt(mUuid + ".deletePolicy", -1);
- assertEquals(Account.DELETE_POLICY_ON_DELETE, storedPolicy);
- }
-
- /**
- * Create a dummy account with minimal fields
- */
- private void createTestAccount() {
- mAccount = new Account(getContext());
- mAccount.save(mPreferences);
-
- mUuid = mAccount.getUuid();
- }
-
-}
diff --git a/tests/src/com/android/email/PreferencesUnitTests.java b/tests/src/com/android/email/PreferencesUnitTests.java
deleted file mode 100644
index 3216ccea1..000000000
--- a/tests/src/com/android/email/PreferencesUnitTests.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email;
-
-import android.content.SharedPreferences;
-import android.net.Uri;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-/**
- * This is a series of unit tests for the Preferences class.
- *
- * Technically these are functional because they use the underlying preferences framework. It
- * would be a really good idea if we could inject our own underlying preferences storage, to better
- * test cases like zero accounts behavior (right now, we have to allow for any number of accounts
- * already being on the device, and not trashing any.)
- */
-@SmallTest
-public class PreferencesUnitTests extends AndroidTestCase {
-
- private Preferences mPreferences;
-
- private String mUuid;
- private Account mAccount;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- mPreferences = Preferences.getPreferences(getContext());
- }
-
- /**
- * Delete any dummy accounts we set up for this test
- */
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
-
- if (mAccount != null && mPreferences != null) {
- mAccount.delete(mPreferences);
- }
- }
-
- /**
- * Test the new getAccountByContentUri() API. This should return null if no
- * accounts are configured, or the Uri doesn't match, and it should return a desired account
- * otherwise.
- *
- * TODO: Not actually testing the no-accounts case
- */
- public void testGetAccountByContentUri() {
- // Create a dummy account
- createTestAccount();
-
- // test sunny-day lookup by Uri
- Uri testAccountUri = mAccount.getContentUri();
- Account lookup = mPreferences.getAccountByContentUri(testAccountUri);
- assertEquals(mAccount, lookup);
-
- // now make it a bogus Uri - bad scheme, good path, good UUID
- testAccountUri = Uri.parse("bogus://accounts/" + mAccount.getUuid());
- lookup = mPreferences.getAccountByContentUri(testAccountUri);
- assertNull(lookup);
-
- // now make it a bogus Uri - good scheme, bad path, good UUID
- testAccountUri = Uri.parse("content://bogus/" + mAccount.getUuid());
- lookup = mPreferences.getAccountByContentUri(testAccountUri);
- assertNull(lookup);
-
- // now make it a bogus Uri - good scheme/path, bad UUID
- testAccountUri = Uri.parse("content://accounts/" + mAccount.getUuid() + "-bogus");
- lookup = mPreferences.getAccountByContentUri(testAccountUri);
- assertNull(lookup);
- }
-
- /**
- * Create a dummy account with minimal fields
- */
- private void createTestAccount() {
- mAccount = new Account(getContext());
- mAccount.save(mPreferences);
-
- mUuid = mAccount.getUuid();
- }
-
-}
diff --git a/tests/src/com/android/email/SmallTests.java b/tests/src/com/android/email/SmallTests.java
deleted file mode 100644
index b9878ff27..000000000
--- a/tests/src/com/android/email/SmallTests.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import android.test.suitebuilder.TestSuiteBuilder;
-
-/**
- * Unit & small test suites for Email. This is intended to run all tests that can be handled
- * locally, without requiring any external email server.
- *
- * To run just this suite from the command line:
- * $ adb shell am instrument -w \
- * -e class com.android.email.UnitTests \
- * com.android.email.tests/android.test.InstrumentationTestRunner
- */
-public class SmallTests extends TestSuite {
-
- public static Test suite() {
- return new TestSuiteBuilder(SmallTests.class)
- .includeAllPackagesUnderHere()
- .build();
- }
-}
diff --git a/tests/src/com/android/email/UtilityUnitTests.java b/tests/src/com/android/email/UtilityUnitTests.java
deleted file mode 100644
index 00517742d..000000000
--- a/tests/src/com/android/email/UtilityUnitTests.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email;
-
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * This is a series of unit tests for the Utility class. These tests must be locally
- * complete - no server(s) required.
- */
-@SmallTest
-public class UtilityUnitTests extends TestCase {
-
- /**
- * Tests of the IMAP quoting rules function.
- */
- public void testImapQuote() {
-
- // Simple strings should come through with simple quotes
- assertEquals("\"abcd\"", Utility.imapQuoted("abcd"));
-
- // Quoting internal double quotes with \
- assertEquals("\"ab\\\"cd\"", Utility.imapQuoted("ab\"cd"));
-
- // Quoting internal \ with \\
- assertEquals("\"ab\\\\cd\"", Utility.imapQuoted("ab\\cd"));
- }
-
-}
diff --git a/tests/src/com/android/email/activity/FolderMessageListUnitTests.java b/tests/src/com/android/email/activity/FolderMessageListUnitTests.java
deleted file mode 100644
index e23333a57..000000000
--- a/tests/src/com/android/email/activity/FolderMessageListUnitTests.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity;
-
-import com.android.email.Account;
-import com.android.email.Preferences;
-
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.net.Uri;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-/**
- * This is a series of unit tests for the Preferences class.
- *
- * This is just unit tests of simple statics - the activity is not instantiated
- */
-@SmallTest
-public class FolderMessageListUnitTests extends AndroidTestCase {
-
- private Preferences mPreferences;
-
- private String mUuid;
- private Account mAccount;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- mPreferences = Preferences.getPreferences(getContext());
- }
-
- /**
- * Delete any dummy accounts we set up for this test
- */
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
-
- if (mAccount != null && mPreferences != null) {
- mAccount.delete(mPreferences);
- }
- }
-
- /**
- * Test of actionHandleAccount() variants. Make sure they generate correct intents and
- * then call startActivity() with them.
- */
- public void testActionHandleAccount() {
- // Create a dummy account
- createTestAccount();
-
- // Create a mock context to catch the startActivity calls
- MyContext mockContext = new MyContext(getContext());
-
- // First, try with no initial folder
- FolderMessageList.actionHandleAccount(mockContext, mAccount);
- Intent i = mockContext.startActivityIntent;
- assertNotNull(i);
- checkIntent(i, null, mAccount, null);
-
- // Next try with initial folder specified
- FolderMessageList.actionHandleAccount(mockContext, mAccount, "test-folder-name");
- i = mockContext.startActivityIntent;
- assertNotNull(i);
- checkIntent(i, null, mAccount, "test-folder-name");
- }
-
- /**
- * Test of actionHandleAccountIntent(). Make sure it generates correct intents.
- */
- public void testActionHandleAccountIntent() {
- // Create a dummy account
- createTestAccount();
-
- // First try with no initial folder
- Intent result = FolderMessageList.actionHandleAccountIntent(
- getContext(), mAccount, null);
- checkIntent(result, null, mAccount, null);
-
- // now try with a specified initial folder
- result = FolderMessageList.actionHandleAccountIntent(
- getContext(), mAccount, "test-folder-name");
- checkIntent(result, null, mAccount, "test-folder-name");
- }
-
- /**
- * Test of actionHandleAccountUriIntent(). Make sure it generates correct intents.
- */
- public void testActionHandleAccountUriIntent() {
- // Create a dummy account
- createTestAccount();
-
- // First try with no initial folder
- Intent result = FolderMessageList.actionHandleAccountUriIntent(
- getContext(), mAccount, null);
- checkIntent(result, mAccount.getContentUri(), null, null);
-
- // now try with a specified initial folder
- result = FolderMessageList.actionHandleAccountUriIntent(
- getContext(), mAccount, "test-folder-name");
- checkIntent(result, mAccount.getContentUri(), null, "test-folder-name");
- }
-
- /**
- * Check the values in a generated intent
- */
- private void checkIntent(Intent i,
- Uri expectData, Account expectAccount, String expectFolder) {
-
- Uri resultUri = i.getData();
- assertEquals(expectData, resultUri);
-
- Account resultAccount = (Account) i.getSerializableExtra("account");
- assertEquals(expectAccount, resultAccount);
-
- String resultFolder = i.getStringExtra("initialFolder");
- assertEquals(expectFolder, resultFolder);
- }
-
- /**
- * Create a dummy account with minimal fields
- */
- private void createTestAccount() {
- mAccount = new Account(getContext());
- mAccount.save(mPreferences);
-
- mUuid = mAccount.getUuid();
- }
-
- /**
- * Mock Context so we can catch the startActivity call in actionHandleAccount()
- */
- private static class MyContext extends ContextWrapper {
-
- Intent startActivityIntent = null;
-
- public MyContext(Context base) {
- super(base);
- }
-
- @Override
- public void startActivity(Intent i) {
- startActivityIntent = i;
- }
-
-
- }
-
-}
diff --git a/tests/src/com/android/email/activity/MessageComposeInstrumentationTests.java b/tests/src/com/android/email/activity/MessageComposeInstrumentationTests.java
deleted file mode 100644
index 4ccce60a6..000000000
--- a/tests/src/com/android/email/activity/MessageComposeInstrumentationTests.java
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity;
-
-import com.android.email.Account;
-import com.android.email.Email;
-import com.android.email.Preferences;
-import com.android.email.R;
-import com.android.email.activity.MessageCompose;
-import com.android.email.mail.Address;
-import com.android.email.mail.Message;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Message.RecipientType;
-import com.android.email.mail.internet.MimeMessage;
-import com.android.email.mail.internet.TextBody;
-
-import android.content.Intent;
-import android.net.Uri;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.view.KeyEvent;
-import android.view.View;
-import android.widget.EditText;
-import android.content.Context;
-
-/**
- * Various instrumentation tests for MessageCompose.
- *
- * It might be possible to convert these to ActivityUnitTest, which would be faster.
- */
-@MediumTest
-public class MessageComposeInstrumentationTests
- extends ActivityInstrumentationTestCase2<MessageCompose> {
-
- private EditText mToView;
- private EditText mSubjectView;
- private EditText mMessageView;
-
- private static final String SENDER = "sender@android.com";
- private static final String REPLYTO = "replyto@android.com";
- private static final String RECIPIENT_TO = "recipient-to@android.com";
- private static final String RECIPIENT_CC = "recipient-cc@android.com";
- private static final String RECIPIENT_BCC = "recipient-bcc@android.com";
- private static final String SUBJECT = "This is the subject";
- private static final String BODY = "This is the body. This is also the body.";
-
- /** Note - these are copied from private strings in MessageCompose. Make them package? */
- private static final String ACTION_REPLY = "com.android.email.intent.action.REPLY";
- private static final String ACTION_REPLY_ALL = "com.android.email.intent.action.REPLY_ALL";
- private static final String ACTION_FORWARD = "com.android.email.intent.action.FORWARD";
- private static final String ACTION_EDIT_DRAFT = "com.android.email.intent.action.EDIT_DRAFT";
-
- public MessageComposeInstrumentationTests() {
- super("com.android.email", MessageCompose.class);
- }
-
- /*
- * The Message Composer activity is only enabled if one or more accounts
- * are configured on the device and a default account has been specified,
- * so we do that here before every test.
- */
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- Context context = getInstrumentation().getTargetContext();
- Account[] accounts = Preferences.getPreferences(context).getAccounts();
- if (accounts.length > 0)
- {
- // This depends on getDefaultAccount() to auto-assign the default account, if necessary
- Preferences.getPreferences(context).getDefaultAccount();
- Email.setServicesEnabled(context);
- }
- final MessageCompose a = getActivity();
- mToView = (EditText) a.findViewById(R.id.to);
- mSubjectView = (EditText) a.findViewById(R.id.subject);
- mMessageView = (EditText) a.findViewById(R.id.message_content);
- }
-
- /**
- * The name 'test preconditions' is a convention to signal that if this
- * test doesn't pass, the test case was not set up properly and it might
- * explain any and all failures in other tests. This is not guaranteed
- * to run before other tests, as junit uses reflection to find the tests.
- */
- public void testPreconditions() {
- assertNotNull(mToView);
- assertEquals(0, mToView.length());
- assertNotNull(mSubjectView);
- assertEquals(0, mSubjectView.length());
- assertNotNull(mMessageView);
- assertEquals(0, mMessageView.length());
- }
-
- /**
- * Test a couple of variations of processSourceMessage() for REPLY
- * To = Reply-To or From: (if REPLY)
- * To = (Reply-To or From:) + To: + Cc: (if REPLY_ALL)
- * Subject = Re: Subject
- * Body = empty (and has cursor)
- *
- * TODO test REPLY_ALL
- */
- public void testProcessSourceMessageReply() throws MessagingException, Throwable {
-
- final Message message = buildTestMessage(RECIPIENT_TO, SENDER, SUBJECT, BODY);
- Intent intent = new Intent(ACTION_REPLY);
- final MessageCompose a = getActivity();
- a.setIntent(intent);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- a.processSourceMessage(message);
- checkFields(SENDER + ", ", null, null, "Re: " + SUBJECT, null);
- checkFocused(mMessageView);
- }
- });
-
- message.setFrom(null);
- message.setReplyTo(Address.parse(REPLYTO));
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- resetViews();
- a.processSourceMessage(message);
- checkFields(REPLYTO + ", ", null, null, "Re: " + SUBJECT, null);
- checkFocused(mMessageView);
- }
- });
- }
-
- /**
- * Test processSourceMessage() for FORWARD
- * To = empty (and has cursor)
- * Subject = Fwd: Subject
- * Body = empty
- */
- public void testProcessSourceMessageForward() throws MessagingException, Throwable {
-
- final Message message = buildTestMessage(RECIPIENT_TO, SENDER, SUBJECT, BODY);
- Intent intent = new Intent(ACTION_FORWARD);
- final MessageCompose a = getActivity();
- a.setIntent(intent);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- a.processSourceMessage(message);
- checkFields(null, null, null, "Fwd: " + SUBJECT, null);
- checkFocused(mToView);
- }
- });
- }
-
- /**
- * Test processSourceMessage() for EDIT_DRAFT
- * Reply and ReplyAll should map:
- * To = to
- * Subject = Subject
- * Body = body (has cursor)
- *
- * TODO check CC and BCC handling too
- */
- public void testProcessSourceMessageDraft() throws MessagingException, Throwable {
-
- final Message message = buildTestMessage(RECIPIENT_TO, SENDER, SUBJECT, BODY);
- Intent intent = new Intent(ACTION_EDIT_DRAFT);
- final MessageCompose a = getActivity();
- a.setIntent(intent);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- a.processSourceMessage(message);
- checkFields(RECIPIENT_TO + ", ", null, null, SUBJECT, BODY);
- checkFocused(mMessageView);
- }
- });
-
- // if subject is null, then cursor should be there instead
-
- message.setSubject("");
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- resetViews();
- a.processSourceMessage(message);
- checkFields(RECIPIENT_TO + ", ", null, null, null, BODY);
- checkFocused(mSubjectView);
- }
- });
-
- }
-
- /**
- * Test for processing of Intent EXTRA_* fields that impact the headers:
- * Intent.EXTRA_EMAIL, Intent.EXTRA_CC, Intent.EXTRA_BCC, Intent.EXTRA_SUBJECT
- */
- public void testIntentHeaderExtras() throws MessagingException, Throwable {
-
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.putExtra(Intent.EXTRA_EMAIL, new String[] { RECIPIENT_TO });
- intent.putExtra(Intent.EXTRA_CC, new String[] { RECIPIENT_CC });
- intent.putExtra(Intent.EXTRA_BCC, new String[] { RECIPIENT_BCC });
- intent.putExtra(Intent.EXTRA_SUBJECT, SUBJECT);
-
- final MessageCompose a = getActivity();
- final Intent i2 = new Intent(intent);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- a.initFromIntent(i2);
- checkFields(RECIPIENT_TO + ", ", RECIPIENT_CC, RECIPIENT_BCC, SUBJECT, null);
- checkFocused(mMessageView);
- }
- });
- }
-
- /**
- * Test for processing of a typical browser "share" intent, e.g.
- * type="text/plain", EXTRA_TEXT="http:link.server.com"
- */
- public void testIntentSendPlainText() throws MessagingException, Throwable {
-
- Intent intent = new Intent(Intent.ACTION_SEND);
- intent.setType("text/plain");
- intent.putExtra(Intent.EXTRA_TEXT, BODY);
-
- final MessageCompose a = getActivity();
- final Intent i2 = new Intent(intent);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- a.initFromIntent(i2);
- checkFields(null, null, null, null, BODY);
- checkFocused(mToView);
- }
- });
- }
-
- /**
- * Test for processing of a typical browser Mailto intent, e.g.
- * action=android.intent.action.VIEW
- * categories={android.intent.category.BROWSABLE}
- * data=mailto:user@domain.com?subject=This%20is%20%the%subject
- */
- public void testBrowserMailToIntent() throws MessagingException, Throwable {
-
- Intent intent = new Intent(Intent.ACTION_VIEW);
- Uri uri = Uri.parse("mailto:" + RECIPIENT_TO + "?subject=This%20is%20the%20subject");
- intent.setData(uri);
-
- final MessageCompose a = getActivity();
- final Intent i2 = new Intent(intent);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- a.initFromIntent(i2);
- checkFields(RECIPIENT_TO + ", ", null, null, "This is the subject", null);
- checkFocused(mMessageView);
- }
- });
- }
-
- /**
- * TODO: test mailto: with simple encoding mode
- * TODO: test mailto: URI with all optional fields
- * TODO: come up with a way to add a very small attachment
- * TODO: confirm the various details between handling of SEND, VIEW, SENDTO
- */
-
- /**
- * Helper method to quickly check (and assert) on the to, subject, and content views.
- *
- * @param to expected value (null = it must be empty)
- * @param cc expected value (null = it must be empty)
- * @param bcc expected value (null = it must be empty)
- * @param subject expected value (null = it must be empty)
- * @param content expected value (null = it must be empty)
- */
- private void checkFields(String to, String cc, String bcc, String subject, String content) {
- String toText = mToView.getText().toString();
- if (to == null) {
- assertEquals(0, toText.length());
- } else {
- assertEquals(to, toText);
- }
-
- String subjectText = mSubjectView.getText().toString();
- if (subject == null) {
- assertEquals(0, subjectText.length());
- } else {
- assertEquals(subject, subjectText);
- }
-
- String contentText = mMessageView.getText().toString();
- if (content == null) {
- assertEquals(0, contentText.length());
- } else {
- assertEquals(content, contentText);
- }
- }
-
- /**
- * Helper method to verify which field has the focus
- * @param focused The view that should be focused (all others should not have focus)
- */
- private void checkFocused(View focused) {
- assertEquals(focused == mToView, mToView.isFocused());
- assertEquals(focused == mSubjectView, mSubjectView.isFocused());
- assertEquals(focused == mMessageView, mMessageView.isFocused());
- }
-
- /**
- * Helper used when running multiple calls to processSourceMessage within a test method.
- * Simply clears out the views, so that we get fresh data and not appended data.
- *
- * Must call from UI thread.
- */
- private void resetViews() {
- mToView.setText(null);
- mSubjectView.setText(null);
- mMessageView.setText(null);
- }
-
- /**
- * Build a test message that can be used as input to processSourceMessage
- *
- * @param to Recipient(s) of the message
- * @param sender Sender(s) of the message
- * @param subject Subject of the message
- * @param content Content of the message
- * @return a complete Message object
- */
- private Message buildTestMessage(String to, String sender, String subject, String content)
- throws MessagingException {
- Message message = new MimeMessage();
-
- if (to != null) {
- Address[] addresses = Address.parse(to);
- message.setRecipients(RecipientType.TO, addresses);
- }
-
- if (sender != null) {
- Address[] addresses = Address.parse(sender);
- message.setFrom(Address.parse(sender)[0]);
- }
-
- if (subject != null) {
- message.setSubject(subject);
- }
-
- if (content != null) {
- TextBody body = new TextBody(content);
- message.setBody(body);
- }
-
- return message;
- }
-
- /**
- * Tests for the comma-inserting logic. The logic is applied equally to To: Cc: and Bcc:
- * but we only run the full set on To:
- */
- public void testCommaInserting() throws Throwable {
- // simple appending cases
- checkCommaInsert("a", "", false);
- checkCommaInsert("a@", "", false);
- checkCommaInsert("a@b", "", false);
- checkCommaInsert("a@b.", "", true); // non-optimal, but matches current implementation
- checkCommaInsert("a@b.c", "", true);
-
- // confirm works properly for internal editing
- checkCommaInsert("me@foo.com, you", " they@bar.com", false);
- checkCommaInsert("me@foo.com, you@", "they@bar.com", false);
- checkCommaInsert("me@foo.com, you@bar", " they@bar.com", false);
- checkCommaInsert("me@foo.com, you@bar.", " they@bar.com", true); // non-optimal
- checkCommaInsert("me@foo.com, you@bar.com", " they@bar.com", true);
-
- // check a couple of multi-period cases
- checkCommaInsert("me.myself@foo", "", false);
- checkCommaInsert("me.myself@foo.com", "", true);
- checkCommaInsert("me@foo.co.uk", "", true);
-
- // cases that should not append because there's already a comma
- checkCommaInsert("a@b.c,", "", false);
- checkCommaInsert("me@foo.com, you@bar.com,", " they@bar.com", false);
- checkCommaInsert("me.myself@foo.com,", "", false);
- checkCommaInsert("me@foo.co.uk,", "", false);
- }
-
- /**
- * Check comma insertion logic for a single try on the To: field
- */
- private void checkCommaInsert(final String before, final String after, boolean expectComma)
- throws Throwable {
- String expect = new String(before + (expectComma ? ", " : " ") + after);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- mToView.setText(before + after);
- mToView.setSelection(before.length());
- }
- });
- getInstrumentation().sendStringSync(" ");
- String result = mToView.getText().toString();
- assertEquals(expect, result);
-
- }
-
-}
diff --git a/tests/src/com/android/email/activity/MessageViewTests.java b/tests/src/com/android/email/activity/MessageViewTests.java
deleted file mode 100644
index 393eaf420..000000000
--- a/tests/src/com/android/email/activity/MessageViewTests.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity;
-
-import com.android.email.Account;
-import com.android.email.Email;
-import com.android.email.MessagingController;
-import com.android.email.Preferences;
-import com.android.email.R;
-
-import android.content.Context;
-import android.content.Intent;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.view.MenuItem;
-import android.webkit.WebView;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * Various instrumentation tests for MessageCompose.
- *
- * It might be possible to convert these to ActivityUnitTest, which would be faster.
- */
-@MediumTest
-public class MessageViewTests
- extends ActivityInstrumentationTestCase2<MessageView> {
-
- // copied from MessageView (could be package class)
- private static final String EXTRA_ACCOUNT = "com.android.email.MessageView_account";
- private static final String EXTRA_FOLDER = "com.android.email.MessageView_folder";
- private static final String EXTRA_MESSAGE = "com.android.email.MessageView_message";
- private static final String EXTRA_FOLDER_UIDS = "com.android.email.MessageView_folderUids";
- private static final String EXTRA_NEXT = "com.android.email.MessageView_next";
-
- // used by the mock controller
- private static final String FOLDER_NAME = "folder";
- private static final String MESSAGE_UID = "message_uid";
-
- private Account mAccount;
- private TextView mToView;
- private TextView mSubjectView;
- private WebView mMessageContentView;
-
- public MessageViewTests() {
- super("com.android.email", MessageView.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- Context context = getInstrumentation().getTargetContext();
- Account[] accounts = Preferences.getPreferences(context).getAccounts();
- if (accounts.length > 0)
- {
- // This depends on getDefaultAccount() to auto-assign the default account, if necessary
- mAccount = Preferences.getPreferences(context).getDefaultAccount();
- Email.setServicesEnabled(context);
- }
-
- // configure a mock controller
- MessagingController mockController = new MockMessagingController();
- MessagingController.injectMockController(mockController);
-
- // setup an intent to spin up this activity with something useful
- ArrayList<String> FOLDER_UIDS = new ArrayList<String>(
- Arrays.asList(new String[]{ "why", "is", "java", "so", "ugly?" }));
- Intent i = new Intent()
- .putExtra(EXTRA_ACCOUNT, mAccount)
- .putExtra(EXTRA_FOLDER, FOLDER_NAME)
- .putExtra(EXTRA_MESSAGE, MESSAGE_UID)
- .putStringArrayListExtra(EXTRA_FOLDER_UIDS, FOLDER_UIDS);
- this.setActivityIntent(i);
-
- final MessageView a = getActivity();
- mToView = (TextView) a.findViewById(R.id.to);
- mSubjectView = (TextView) a.findViewById(R.id.subject);
- mMessageContentView = (WebView) a.findViewById(R.id.message_content);
- }
-
- /**
- * The name 'test preconditions' is a convention to signal that if this
- * test doesn't pass, the test case was not set up properly and it might
- * explain any and all failures in other tests. This is not guaranteed
- * to run before other tests, as junit uses reflection to find the tests.
- */
- public void testPreconditions() {
- assertNotNull(mToView);
- assertEquals(0, mToView.length());
- assertNotNull(mSubjectView);
- assertEquals(0, mSubjectView.length());
- assertNotNull(mMessageContentView);
- }
-
- /**
- * Tests that various UI calls can be made safely even before the messaging controller
- * has completed loading the message. This catches various race conditions.
- */
- public void testUiRaceConditions() {
-
- MessageView a = getActivity();
-
- // on-streen controls
- a.onClick(a.findViewById(R.id.reply));
- a.onClick(a.findViewById(R.id.reply_all));
- a.onClick(a.findViewById(R.id.delete));
- a.onClick(a.findViewById(R.id.next));
- a.onClick(a.findViewById(R.id.previous));
-// a.onClick(a.findViewById(R.id.download)); // not revealed yet, so unfair test
-// a.onClick(a.findViewById(R.id.view)); // not revealed yet, so unfair test
- a.onClick(a.findViewById(R.id.show_pictures));
-
- // menus
- a.handleMenuItem(R.id.delete);
- a.handleMenuItem(R.id.reply);
- a.handleMenuItem(R.id.reply_all);
- a.handleMenuItem(R.id.forward);
- a.handleMenuItem(R.id.mark_as_unread);
- }
-
- /**
- * Mock Messaging controller, so we can drive its callbacks. This probably should be
- * generalized since we're likely to use for other tests eventually.
- */
- private static class MockMessagingController extends MessagingController {
-
- private MockMessagingController() {
- super(null);
- }
- }
-
-}
diff --git a/tests/src/com/android/email/activity/setup/AccountSetupIncomingTests.java b/tests/src/com/android/email/activity/setup/AccountSetupIncomingTests.java
deleted file mode 100644
index ccb4bea8b..000000000
--- a/tests/src/com/android/email/activity/setup/AccountSetupIncomingTests.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity.setup;
-
-import com.android.email.Account;
-import com.android.email.R;
-
-import android.content.Intent;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.widget.Button;
-import android.widget.EditText;
-
-/**
- * Tests of the basic UI logic in the Account Setup Incoming (IMAP / POP3) screen.
- */
-@MediumTest
-public class AccountSetupIncomingTests extends
- ActivityInstrumentationTestCase2<AccountSetupIncoming> {
-
- private AccountSetupIncoming mActivity;
- private EditText mServerView;
- private Button mNextButton;
-
- public AccountSetupIncomingTests() {
- super("com.android.email", AccountSetupIncoming.class);
- }
-
- /**
- * Common setup code for all tests. Sets up a default launch intent, which some tests
- * will use (others will override).
- */
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- // This sets up a default URI which can be used by any of the test methods below.
- // Individual test methods can replace this with a custom URI if they wish
- // (except those that run on the UI thread - for them, it's too late to change it.)
- Intent i = getTestIntent("imap://user:password@server.com:999");
- setActivityIntent(i);
- }
-
- /**
- * Test processing with a complete, good URI -> good fields
- */
- public void testGoodUri() {
- Intent i = getTestIntent("imap://user:password@server.com:999");
- setActivityIntent(i);
- getActivityAndFields();
- assertTrue(mNextButton.isEnabled());
- }
-
- /**
- * No user is not OK - not enabled
- */
- public void testBadUriNoUser() {
- Intent i = getTestIntent("imap://:password@server.com:999");
- setActivityIntent(i);
- getActivityAndFields();
- assertFalse(mNextButton.isEnabled());
- }
-
- /**
- * No password is not OK - not enabled
- */
- public void testBadUriNoPassword() {
- Intent i = getTestIntent("imap://user@server.com:999");
- setActivityIntent(i);
- getActivityAndFields();
- assertFalse(mNextButton.isEnabled());
- }
-
- /**
- * No port is OK - still enabled
- */
- public void testGoodUriNoPort() {
- Intent i = getTestIntent("imap://user:password@server.com");
- setActivityIntent(i);
- getActivityAndFields();
- assertTrue(mNextButton.isEnabled());
- }
-
- /**
- * Test for non-standard but OK server names
- */
- @UiThreadTest
- public void testGoodServerVariants() {
- getActivityAndFields();
- assertTrue(mNextButton.isEnabled());
-
- mServerView.setText(" server.com ");
- assertTrue(mNextButton.isEnabled());
- }
-
- /**
- * Test for non-empty but non-OK server names
- */
- @UiThreadTest
- public void testBadServerVariants() {
- getActivityAndFields();
- assertTrue(mNextButton.isEnabled());
-
- mServerView.setText(" ");
- assertFalse(mNextButton.isEnabled());
-
- mServerView.setText("serv$er.com");
- assertFalse(mNextButton.isEnabled());
- }
-
- /**
- * TODO: A series of tests to explore the logic around security models & ports
- * TODO: A series of tests exploring differences between IMAP and POP3
- */
-
- /**
- * Get the activity (which causes it to be started, using our intent) and get the UI fields
- */
- private void getActivityAndFields() {
- mActivity = getActivity();
- mServerView = (EditText) mActivity.findViewById(R.id.account_server);
- mNextButton = (Button) mActivity.findViewById(R.id.next);
- }
-
- /**
- * Create an intent with the Account in it
- */
- private Intent getTestIntent(String storeUriString) {
- Account account = new Account(this.getInstrumentation().getTargetContext());
- account.setStoreUri(storeUriString);
- Intent i = new Intent(Intent.ACTION_MAIN);
- i.putExtra("account", account); // AccountSetupNames.EXTRA_ACCOUNT == "account"
- return i;
- }
-
-}
diff --git a/tests/src/com/android/email/activity/setup/AccountSetupNamesTests.java b/tests/src/com/android/email/activity/setup/AccountSetupNamesTests.java
deleted file mode 100644
index 630464d39..000000000
--- a/tests/src/com/android/email/activity/setup/AccountSetupNamesTests.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity.setup;
-
-import com.android.email.Account;
-import com.android.email.R;
-
-import android.content.Intent;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.widget.Button;
-
-/**
- * Tests of basic UI logic in the AccountSetupNamesTest screen.
- */
-@MediumTest
-public class AccountSetupNamesTests extends ActivityInstrumentationTestCase2<AccountSetupNames> {
-
- private AccountSetupNames mActivity;
- private Button mDoneButton;
-
- public AccountSetupNamesTests() {
- super("com.android.email", AccountSetupNames.class);
- }
-
- /**
- * Test a "good" account name (enables the button)
- */
- public void testGoodAccountName() {
- Intent i = getTestIntent("GoodName");
- this.setActivityIntent(i);
-
- getActivityAndFields();
-
- assertTrue(mDoneButton.isEnabled());
- }
-
- /**
- * Test a "bad" account name (disables the button)
- */
- public void testBadAccountName() {
- Intent i = getTestIntent("");
- this.setActivityIntent(i);
-
- getActivityAndFields();
-
- assertFalse(mDoneButton.isEnabled());
- }
-
- /**
- * Get the activity (which causes it to be started, using our intent) and get the UI fields
- */
- private void getActivityAndFields() {
- mActivity = getActivity();
- mDoneButton = (Button) mActivity.findViewById(R.id.done);
- }
-
- /**
- * Create an intent with the Account in it
- */
- private Intent getTestIntent(String name) {
- Account account = new Account(this.getInstrumentation().getTargetContext());
- account.setName(name);
- Intent i = new Intent(Intent.ACTION_MAIN);
- i.putExtra("account", account); // AccountSetupNames.EXTRA_ACCOUNT == "account"
- return i;
- }
-
-}
diff --git a/tests/src/com/android/email/activity/setup/AccountSetupOutgoingTests.java b/tests/src/com/android/email/activity/setup/AccountSetupOutgoingTests.java
deleted file mode 100644
index 539391fcb..000000000
--- a/tests/src/com/android/email/activity/setup/AccountSetupOutgoingTests.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.activity.setup;
-
-import com.android.email.Account;
-import com.android.email.R;
-
-import android.content.Intent;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.widget.Button;
-import android.widget.EditText;
-
-/**
- * Tests of the basic UI logic in the Account Setup Outgoing (SMTP) screen.
- */
-@MediumTest
-public class AccountSetupOutgoingTests extends
- ActivityInstrumentationTestCase2<AccountSetupOutgoing> {
-
- private AccountSetupOutgoing mActivity;
- private EditText mServerView;
- private Button mNextButton;
-
- public AccountSetupOutgoingTests() {
- super("com.android.email", AccountSetupOutgoing.class);
- }
-
- /**
- * Common setup code for all tests. Sets up a default launch intent, which some tests
- * will use (others will override).
- */
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- // This sets up a default URI which can be used by any of the test methods below.
- // Individual test methods can replace this with a custom URI if they wish
- // (except those that run on the UI thread - for them, it's too late to change it.)
- Intent i = getTestIntent("smtp://user:password@server.com:999");
- setActivityIntent(i);
- }
-
- /**
- * Test processing with a complete, good URI -> good fields
- */
- public void testGoodUri() {
- getActivityAndFields();
- assertTrue(mNextButton.isEnabled());
- }
-
- /**
- * No user is not OK - not enabled
- */
- public void testBadUriNoUser() {
- Intent i = getTestIntent("smtp://:password@server.com:999");
- setActivityIntent(i);
- getActivityAndFields();
- assertFalse(mNextButton.isEnabled());
- }
-
- /**
- * No password is not OK - not enabled
- */
- public void testBadUriNoPassword() {
- Intent i = getTestIntent("smtp://user@server.com:999");
- setActivityIntent(i);
- getActivityAndFields();
- assertFalse(mNextButton.isEnabled());
- }
-
- /**
- * No port is OK - still enabled
- */
- public void testGoodUriNoPort() {
- Intent i = getTestIntent("smtp://user:password@server.com");
- setActivityIntent(i);
- getActivityAndFields();
- assertTrue(mNextButton.isEnabled());
- }
-
- /**
- * Test for non-standard but OK server names
- */
- @UiThreadTest
- public void testGoodServerVariants() {
- getActivityAndFields();
- assertTrue(mNextButton.isEnabled());
-
- mServerView.setText(" server.com ");
- assertTrue(mNextButton.isEnabled());
- }
-
- /**
- * Test for non-empty but non-OK server names
- */
- @UiThreadTest
- public void testBadServerVariants() {
- getActivityAndFields();
- assertTrue(mNextButton.isEnabled());
-
- mServerView.setText(" ");
- assertFalse(mNextButton.isEnabled());
-
- mServerView.setText("serv$er.com");
- assertFalse(mNextButton.isEnabled());
- }
-
- /**
- * TODO: A series of tests to explore the logic around security models & ports
- */
-
- /**
- * Get the activity (which causes it to be started, using our intent) and get the UI fields
- */
- private void getActivityAndFields() {
- mActivity = getActivity();
- mServerView = (EditText) mActivity.findViewById(R.id.account_server);
- mNextButton = (Button) mActivity.findViewById(R.id.next);
- }
-
- /**
- * Create an intent with the Account in it
- */
- private Intent getTestIntent(String senderUriString) {
- Account account = new Account(this.getInstrumentation().getTargetContext());
- account.setSenderUri(senderUriString);
- Intent i = new Intent(Intent.ACTION_MAIN);
- i.putExtra("account", account); // AccountSetupNames.EXTRA_ACCOUNT == "account"
- return i;
- }
-
-}
diff --git a/tests/src/com/android/email/codec/binary/Base64Test.java b/tests/src/com/android/email/codec/binary/Base64Test.java
deleted file mode 100644
index 9d22b9f71..000000000
--- a/tests/src/com/android/email/codec/binary/Base64Test.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.codec.binary;
-
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * A series of tests of the Base64 encoder.
- */
-@SmallTest
-public class Base64Test extends TestCase {
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
- /**
- * Looking for issues with line length and trailing zeros. The code we're modeling is
- * in mail.internet.TextBody:
- * byte[] bytes = mBody.getBytes("UTF-8");
- * out.write(Base64.encodeBase64Chunked(bytes));
- */
- public void testLineLength54() {
- byte[] out = Base64.encodeBase64Chunked(getByteArray(54));
- checkBase64Structure(out, 1);
- }
- public void testLineLength55() {
- byte[] out = Base64.encodeBase64Chunked(getByteArray(55));
- checkBase64Structure(out, 1);
- }
- public void testLineLength56() {
- byte[] out = Base64.encodeBase64Chunked(getByteArray(56));
- checkBase64Structure(out, 1);
- }
- public void testLineLength57() {
- byte[] out = Base64.encodeBase64Chunked(getByteArray(57));
- checkBase64Structure(out, 1);
- }
- public void testLineLength58() {
- byte[] out = Base64.encodeBase64Chunked(getByteArray(58));
- checkBase64Structure(out, 2);
- }
- public void testLineLength59() {
- byte[] out = Base64.encodeBase64Chunked(getByteArray(59));
- checkBase64Structure(out, 2);
- }
-
- /**
- * Repeat the above tests with 2x line lengths
- */
- public void testLineLength111() {
- byte[] out = Base64.encodeBase64Chunked(getByteArray(111));
- checkBase64Structure(out, 2);
- }
- public void testLineLength112() {
- byte[] out = Base64.encodeBase64Chunked(getByteArray(112));
- checkBase64Structure(out, 2);
- }
- public void testLineLength113() {
- byte[] out = Base64.encodeBase64Chunked(getByteArray(113));
- checkBase64Structure(out, 2);
- }
- public void testLineLength114() {
- byte[] out = Base64.encodeBase64Chunked(getByteArray(114));
- checkBase64Structure(out, 2);
- }
- public void testLineLength115() {
- byte[] out = Base64.encodeBase64Chunked(getByteArray(115));
- checkBase64Structure(out, 3);
- }
-
- /**
- * Validate that base64 output is structurally sound. Does not independently confirm
- * that the actual encoding is valid.
- */
- private void checkBase64Structure(byte[] buffer, int expectedChunks) {
-
- // outer loop - divide into chunks
- int chunkCount = 0;
- int chunkStart;
- int nextChunkStart = 0;
- int limit = buffer.length;
- while (nextChunkStart < limit) {
- chunkStart = -1;
- int chunkEnd;
- for (chunkEnd = nextChunkStart; chunkEnd < limit; ++chunkEnd) {
- assertFalse("nulls in chunk", buffer[chunkEnd] == 0);
- if (buffer[chunkEnd] == '\r') {
- assertTrue(buffer[chunkEnd+1] == '\n');
- chunkStart = nextChunkStart;
- break;
- }
- if (chunkEnd == limit) {
- chunkStart = nextChunkStart;
- break;
- }
- }
- chunkCount++;
- nextChunkStart = chunkEnd + 2;
- assertTrue("chunk not found", chunkStart >= 0);
-
- // At this point we have a single chunk from chunkStart to chunkEnd
- // And we can analyze it for structural correctness
- int chunkLen = chunkEnd - chunkStart;
-
- // Max chunk length
- assertTrue("chunk length <= 76", chunkLen <= 76);
-
- // Multiple of 4 (every 3 bytes of source -> 4 bytes of output)
- assertEquals("chunk length mod 4", 0, chunkLen % 4);
-
- // 0, 1 or 2 '=' at the end
- boolean lastEquals1 = buffer[chunkEnd-1] == '=';
- boolean lastEquals2 = buffer[chunkEnd-2] == '=';
- boolean lastEquals3 = buffer[chunkEnd-3] == '=';
-
- assertTrue("trailing equals",
- (!lastEquals1 && !lastEquals2) || // 0
- (lastEquals1 && !lastEquals2) || // or 1
- (lastEquals1 && lastEquals2)); // or 2
- }
-
- assertEquals("total chunk count", expectedChunks, chunkCount);
- }
-
- /**
- * Generate a test sequence of a given length.
- */
- private byte[] getByteArray(int size) {
- byte[] result = new byte[size];
- byte fillChar = '1';
- for (int i = 0; i < size; ++i) {
- result[i] = fillChar++;
- if (fillChar > '9') {
- fillChar = '0';
- }
- }
- return result;
- }
-}
diff --git a/tests/src/com/android/email/mail/AddressUnitTests.java b/tests/src/com/android/email/mail/AddressUnitTests.java
deleted file mode 100644
index 10d151f24..000000000
--- a/tests/src/com/android/email/mail/AddressUnitTests.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-/**
- * This is a series of unit tests for the Address class. These tests must be locally
- * complete - no server(s) required.
- */
-@SmallTest
-public class AddressUnitTests extends AndroidTestCase {
-
- Address mAddress1;
- Address mAddress2;
- Address mAddress3;
-
- /**
- * Setup code. We generate a handful of Address objects
- */
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- mAddress1 = new Address("address1", "personal1");
- mAddress2 = new Address("address2", "");
- mAddress3 = new Address("address3", null);
- }
-
- /**
- * TODO: test parse()
- */
-
- /**
- * TODO: test toString() (single & list)
- */
-
- /**
- * Test various combinations of the toFriendly (single) method
- */
- public void testToFriendlySingle() {
- assertEquals("personal1", mAddress1.toFriendly());
- assertEquals("address2", mAddress2.toFriendly());
- assertEquals("address3", mAddress3.toFriendly());
- }
-
- /**
- * Test various combinations of the toFriendly (array) method
- */
- public void testToFriendlyArray() {
- Address[] list1 = null;
- Address[] list2 = new Address[0];
- Address[] list3 = new Address[] { mAddress1 };
- Address[] list4 = new Address[] { mAddress1, mAddress2, mAddress3 };
-
- assertEquals(null, Address.toFriendly(list1));
- assertEquals(null, Address.toFriendly(list2));
- assertEquals("personal1", Address.toFriendly(list3));
- assertEquals("personal1,address2,address3", Address.toFriendly(list4));
- }
-
- /**
- * TODO: test pack() and unpack()
- */
-}
diff --git a/tests/src/com/android/email/mail/internet/MimeMessageTest.java b/tests/src/com/android/email/mail/internet/MimeMessageTest.java
deleted file mode 100644
index 8cc6fb51f..000000000
--- a/tests/src/com/android/email/mail/internet/MimeMessageTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.internet;
-
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.internet.MimeMessage;
-
-import junit.framework.TestCase;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-/**
- * This is a series of unit tests for the MimeMessage class. These tests must be locally
- * complete - no server(s) required.
- */
-@SmallTest
-public class MimeMessageTest extends TestCase {
-
- // TODO: more tests.
-
- /**
- * Confirms that setSentDate() correctly set the "Date" header of a Mime message.
- *
- * We tries a same test twice using two locales, Locale.US and the other, since
- * MimeMessage depends on the date formatter, which may emit wrong date format
- * in the locale other than Locale.US.
- * @throws MessagingException
- * @throws ParseException
- */
- public void testSetSentDate() throws MessagingException, ParseException {
- Locale savedLocale = Locale.getDefault();
- Locale.setDefault(Locale.US);
- doTestSetSentDate();
- Locale.setDefault(Locale.JAPAN);
- doTestSetSentDate();
- Locale.setDefault(savedLocale);
- }
-
- private void doTestSetSentDate() throws MessagingException, ParseException {
- // "Thu, 01 Jan 2009 09:00:00 +0000" => 1230800400000L
- long expectedTime = 1230800400000L;
- Date date = new Date(expectedTime);
- MimeMessage message = new MimeMessage();
- message.setSentDate(date);
- String[] headers = message.getHeader("Date");
- assertEquals(1, headers.length);
- // Explicitly specify the locale so that the object does not depend on the default
- // locale.
- SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
-
- Date result = format.parse(headers[0]);
- assertEquals(expectedTime, result.getTime());
- }
-} \ No newline at end of file
diff --git a/tests/src/com/android/email/mail/internet/MimeUtilityTest.java b/tests/src/com/android/email/mail/internet/MimeUtilityTest.java
deleted file mode 100644
index bbc1e9359..000000000
--- a/tests/src/com/android/email/mail/internet/MimeUtilityTest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.internet;
-
-import com.android.email.mail.MessagingException;
-
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * This is a series of unit tests for the MimeUtility class. These tests must be locally
- * complete - no server(s) required.
- */
-@SmallTest
-public class MimeUtilityTest extends TestCase {
-
- // TODO: tests for unfold(String s)
- // TODO: tests for decode(String s)
- // TODO: tests for unfoldAndDecode(String s)
- // TODO: tests for foldAndEncode(String s)
- // TODO: tests for getHeaderParameter(String header, String name)
- // TODO: tests for findFirstPartByMimeType(Part part, String mimeType)
- // TODO: tests for findPartByContentId(Part part, String contentId) throws Exception
-
- /** Tests for getTextFromPart(Part part) */
- public void testGetTextFromPartContentTypeCase() throws MessagingException {
- final String theText = "This is the text of the part";
- TextBody tb = new TextBody(theText);
- MimeBodyPart p = new MimeBodyPart();
-
- // 1. test basic text/plain mode
- p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/plain");
- p.setBody(tb);
- String gotText = MimeUtility.getTextFromPart(p);
- assertEquals(theText, gotText);
-
- // 2. mixed case is OK
- p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "TEXT/PLAIN");
- p.setBody(tb);
- gotText = MimeUtility.getTextFromPart(p);
- assertEquals(theText, gotText);
-
- // 3. wildcards OK
- p.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/other");
- p.setBody(tb);
- gotText = MimeUtility.getTextFromPart(p);
- assertEquals(theText, gotText);
- }
- // TODO: Tests of charset decoding in getTextFromPart()
-
- /** Tests for various aspects of mimeTypeMatches(String mimeType, String matchAgainst) */
- public void testMimeTypeMatches() {
- // 1. No match
- assertFalse(MimeUtility.mimeTypeMatches("foo/bar", "TEXT/PLAIN"));
-
- // 2. Match
- assertTrue(MimeUtility.mimeTypeMatches("text/plain", "text/plain"));
-
- // 3. Match (mixed case)
- assertTrue(MimeUtility.mimeTypeMatches("text/plain", "TEXT/PLAIN"));
- assertTrue(MimeUtility.mimeTypeMatches("TEXT/PLAIN", "text/plain"));
-
- // 4. Match (wildcards)
- assertTrue(MimeUtility.mimeTypeMatches("text/plain", "*/plain"));
- assertTrue(MimeUtility.mimeTypeMatches("text/plain", "text/*"));
- assertTrue(MimeUtility.mimeTypeMatches("text/plain", "*/*"));
-
- // 5. No Match (wildcards)
- assertFalse(MimeUtility.mimeTypeMatches("foo/bar", "*/plain"));
- assertFalse(MimeUtility.mimeTypeMatches("foo/bar", "text/*"));
- }
-
- /** Tests for various aspects of mimeTypeMatches(String mimeType, String[] matchAgainst) */
- public void testMimeTypeMatchesArray() {
- // 1. Zero-length array
- String[] arrayZero = new String[0];
- assertFalse(MimeUtility.mimeTypeMatches("text/plain", arrayZero));
-
- // 2. Single entry, no match
- String[] arrayOne = new String[] { "text/plain" };
- assertFalse(MimeUtility.mimeTypeMatches("foo/bar", arrayOne));
-
- // 3. Single entry, match
- assertTrue(MimeUtility.mimeTypeMatches("text/plain", arrayOne));
-
- // 4. Multi entry, no match
- String[] arrayTwo = new String[] { "text/plain", "match/this" };
- assertFalse(MimeUtility.mimeTypeMatches("foo/bar", arrayTwo));
-
- // 5. Multi entry, match first
- assertTrue(MimeUtility.mimeTypeMatches("text/plain", arrayTwo));
-
- // 6. Multi entry, match not first
- assertTrue(MimeUtility.mimeTypeMatches("match/this", arrayTwo));
- }
-
- // TODO: tests for decodeBody(InputStream in, String contentTransferEncoding)
- // TODO: tests for collectParts(Part part, ArrayList<Part> viewables, ArrayList<Part> attachments)
-}
diff --git a/tests/src/com/android/email/mail/store/ImapStoreUnitTests.java b/tests/src/com/android/email/mail/store/ImapStoreUnitTests.java
deleted file mode 100644
index f1ef6e46e..000000000
--- a/tests/src/com/android/email/mail/store/ImapStoreUnitTests.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.store;
-
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Transport;
-import com.android.email.mail.Folder.OpenMode;
-import com.android.email.mail.internet.BinaryTempFileBody;
-import com.android.email.mail.store.ImapResponseParser;
-import com.android.email.mail.transport.MockTransport;
-
-import java.util.Date;
-import java.util.Locale;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-/**
- * This is a series of unit tests for the ImapStore class. These tests must be locally
- * complete - no server(s) required.
- */
-@SmallTest
-public class ImapStoreUnitTests extends AndroidTestCase {
-
- /* These values are provided by setUp() */
- private ImapStore mStore = null;
- private ImapStore.ImapFolder mFolder = null;
-
- /**
- * Setup code. We generate a lightweight ImapStore and ImapStore.ImapFolder.
- */
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- // These are needed so we can get at the inner classes
- mStore = new ImapStore("imap://user:password@server:999");
- mFolder = (ImapStore.ImapFolder) mStore.getFolder("INBOX");
-
- // This is needed for parsing mime messages
- BinaryTempFileBody.setTempDirectory(this.getContext().getCacheDir());
- }
-
- /**
- * Confirms simple non-SSL non-TLS login
- */
- public void testSimpleLogin() throws MessagingException {
-
- MockTransport mockTransport = openAndInjectMockTransport();
-
- // try to open it
- setupOpenFolder(mockTransport);
- mFolder.open(OpenMode.READ_WRITE);
-
- // TODO: inject specific facts in the initial folder SELECT and check them here
- }
-
- /**
- * Confirms that ImapList object correctly returns an appropriate Date object
- * without throwning MessagingException when getKeyedDate() is called.
- *
- * Here, we try a same test twice using two locales, Locale.US and the other.
- * ImapList uses Locale class internally, and as a result, there's a
- * possibility in which it may throw a MessageException when Locale is
- * not Locale.US. Locale.JAPAN is a typical locale which emits different
- * date formats, which had caused a bug before.
- * @throws MessagingException
- */
- public void testImapListWithUsLocale() throws MessagingException {
- Locale savedLocale = Locale.getDefault();
- Locale.setDefault(Locale.US);
- doTestImapList();
- Locale.setDefault(Locale.JAPAN);
- doTestImapList();
- Locale.setDefault(savedLocale);
- }
-
- private void doTestImapList() throws MessagingException {
- ImapResponseParser parser = new ImapResponseParser(null);
- ImapResponseParser.ImapList list = parser.new ImapList();
- String key = "key";
- String date = "01-Jan-2009 01:00:00 -0800";
- list.add(key);
- list.add(date);
- Date result = list.getKeyedDate(key);
- // "01-Jan-2009 09:00:00 +0000" => 1230800400000L
- assertEquals(1230800400000L, result.getTime());
- }
-
- /**
- * TODO: Test with SSL negotiation (faked)
- * TODO: Test with SSL required but not supported
- * TODO: Test with TLS negotiation (faked)
- * TODO: Test with TLS required but not supported
- * TODO: Test calling getMessageCount(), getMessages(), etc.
- */
-
- /**
- * TODO: Test the operation of checkSettings()
- * TODO: Test small Store & Folder functions that manage folders & namespace
- * TODO: Test small Folder functions that don't really do anything in Imap (if any)
- */
-
- /**
- * TODO: Test the process of opening and indexing a mailbox with one unread message in it.
- */
-
- /**
- * TODO: Test the scenario where the transport is "open" but not really (e.g. server closed).
- /**
- * Set up a basic MockTransport. open it, and inject it into mStore
- */
- private MockTransport openAndInjectMockTransport() {
- // Create mock transport and inject it into the ImapStore that's already set up
- MockTransport mockTransport = new MockTransport();
- mockTransport.setSecurity(Transport.CONNECTION_SECURITY_NONE);
- mStore.setTransport(mockTransport);
- return mockTransport;
- }
-
- /**
- * Helper which stuffs the mock with enough strings to satisfy a call to ImapFolder.open()
- *
- * @param mockTransport the mock transport we're using
- */
- private void setupOpenFolder(MockTransport mockTransport) {
- mockTransport.expect(null, "* OK Imap 2000 Ready To Assist You");
- mockTransport.expect("1 LOGIN user \"password\"",
- "1 OK user authenticated (Success)");
- mockTransport.expect("2 SELECT \"INBOX\"", new String[] {
- "* FLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen)",
- "* OK [PERMANENTFLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen \\*)]",
- "* 0 EXISTS",
- "* 0 RECENT",
- "* OK [UNSEEN 0]",
- "* OK [UIDNEXT 1]",
- "2 OK [READ-WRITE] INBOX selected. (Success)"});
- }
-}
diff --git a/tests/src/com/android/email/mail/store/Pop3StoreUnitTests.java b/tests/src/com/android/email/mail/store/Pop3StoreUnitTests.java
deleted file mode 100644
index 07ec55aad..000000000
--- a/tests/src/com/android/email/mail/store/Pop3StoreUnitTests.java
+++ /dev/null
@@ -1,676 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.store;
-
-import com.android.email.mail.Address;
-import com.android.email.mail.FetchProfile;
-import com.android.email.mail.Flag;
-import com.android.email.mail.Folder;
-import com.android.email.mail.Message;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Transport;
-import com.android.email.mail.Folder.FolderType;
-import com.android.email.mail.Folder.OpenMode;
-import com.android.email.mail.Message.RecipientType;
-import com.android.email.mail.internet.BinaryTempFileBody;
-import com.android.email.mail.transport.MockTransport;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-/**
- * This is a series of unit tests for the POP3 Store class. These tests must be locally
- * complete - no server(s) required.
- */
-@SmallTest
-public class Pop3StoreUnitTests extends AndroidTestCase {
-
- final String UNIQUE_ID_1 = "20080909002219r1800rrjo9e00";
-
- final static int PER_MESSAGE_SIZE = 100;
-
- /* These values are provided by setUp() */
- private Pop3Store mStore = null;
- private Pop3Store.Pop3Folder mFolder = null;
-
- /**
- * Setup code. We generate a lightweight Pop3Store and Pop3Store.Pop3Folder.
- */
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- // These are needed so we can get at the inner classes
- mStore = new Pop3Store("pop3://user:password@server:999");
- mFolder = (Pop3Store.Pop3Folder) mStore.getFolder("INBOX");
-
- // This is needed for parsing mime messages
- BinaryTempFileBody.setTempDirectory(this.getContext().getCacheDir());
- }
-
- /**
- * Test various sunny-day operations of UIDL parser for multi-line responses
- */
- public void testUIDLParserMulti() {
-
- // multi-line mode
- Pop3Store.Pop3Folder.UidlParser parser = mFolder.new UidlParser();
-
- // Test basic in-list UIDL
- parser.parseMultiLine("101 " + UNIQUE_ID_1);
- assertEquals(101, parser.mMessageNumber);
- assertEquals(UNIQUE_ID_1, parser.mUniqueId);
- assertFalse(parser.mEndOfMessage);
- assertFalse(parser.mErr);
-
- // Test end-of-list
- parser.parseMultiLine(".");
- assertTrue(parser.mEndOfMessage);
- assertFalse(parser.mErr);
- }
-
- /**
- * Test various sunny-day operations of UIDL parser for single-line responses
- */
- public void testUIDLParserSingle() {
-
- // single-line mode
- Pop3Store.Pop3Folder.UidlParser parser = mFolder.new UidlParser();
-
- // Test single-message OK response
- parser.parseSingleLine("+OK 101 " + UNIQUE_ID_1);
- assertEquals(101, parser.mMessageNumber);
- assertEquals(UNIQUE_ID_1, parser.mUniqueId);
- assertTrue(parser.mEndOfMessage);
-
- // Test single-message ERR response
- parser.parseSingleLine("-ERR what???");
- assertTrue(parser.mErr);
- }
-
- /**
- * Tests that variants on the RFC-specified formatting of UIDL work properly.
- */
- public void testUIDLComcastVariant() {
-
- // multi-line mode
- Pop3Store.Pop3Folder.UidlParser parser = mFolder.new UidlParser();
-
- // Comcast servers send multiple spaces in their darn UIDL strings.
- parser.parseMultiLine("101 " + UNIQUE_ID_1);
- assertEquals(101, parser.mMessageNumber);
- assertEquals(UNIQUE_ID_1, parser.mUniqueId);
- assertFalse(parser.mEndOfMessage);
- assertFalse(parser.mErr);
- }
-
- /**
- * Confirms simple non-SSL non-TLS login
- */
- public void testSimpleLogin() throws MessagingException {
-
- MockTransport mockTransport = openAndInjectMockTransport();
-
- // try to open it
- setupOpenFolder(mockTransport, 0, null);
- mFolder.open(OpenMode.READ_ONLY);
- }
-
- /**
- * TODO: Test with SSL negotiation (faked)
- * TODO: Test with SSL required but not supported
- * TODO: Test with TLS negotiation (faked)
- * TODO: Test with TLS required but not supported
- * TODO: Test calling getMessageCount(), getMessages(), etc.
- */
-
- /**
- * Test the operation of checkSettings(), which requires (a) a good open and (b) UIDL support.
- */
- public void testCheckSettings() throws MessagingException {
-
- MockTransport mockTransport = openAndInjectMockTransport();
-
- // scenario 1: CAPA returns -ERR, so we try UIDL explicitly
- setupOpenFolder(mockTransport, 0, null);
- setupUidlSequence(mockTransport, 1);
- mockTransport.expect("QUIT", "");
- mStore.checkSettings();
-
- // scenario 2: CAPA indicates UIDL, so we don't try UIDL
- setupOpenFolder(mockTransport, 0, "UIDL");
- mockTransport.expect("QUIT", "");
- mStore.checkSettings();
-
- // scenario 3: CAPA returns -ERR, and UIDL fails
- try {
- setupOpenFolder(mockTransport, 0, null);
- mockTransport.expect("UIDL", "-ERR unsupported");
- mockTransport.expect("QUIT", "");
- mStore.checkSettings();
- fail("MessagingException was expected due to UIDL unsupported.");
- } catch (MessagingException me) {
- // this is expected, so eat it
- }
- }
-
- /**
- * Test small Store & Folder functions that manage folders & namespace
- */
- public void testStoreFoldersFunctions() throws MessagingException {
-
- // getPersonalNamespaces() always returns INBOX folder
- Folder[] folders = mStore.getPersonalNamespaces();
- assertEquals(1, folders.length);
- assertSame(mFolder, folders[0]);
-
- // getName() returns the name we were created with. If "inbox", converts to INBOX
- assertEquals("INBOX", mFolder.getName());
- Pop3Store.Pop3Folder folderMixedCaseInbox = mStore.new Pop3Folder("iNbOx");
- assertEquals("INBOX", folderMixedCaseInbox.getName());
- Pop3Store.Pop3Folder folderNotInbox = mStore.new Pop3Folder("NOT-INBOX");
- assertEquals("NOT-INBOX", folderNotInbox.getName());
-
- // exists() true if name is INBOX
- assertTrue(mFolder.exists());
- assertTrue(folderMixedCaseInbox.exists());
- assertFalse(folderNotInbox.exists());
- }
-
- /**
- * Test small Folder functions that don't really do anything in Pop3
- */
- public void testSmallFolderFunctions() throws MessagingException {
-
- // getMode() returns OpenMode.READ_ONLY
- assertEquals(OpenMode.READ_ONLY, mFolder.getMode());
-
- // create() return false
- assertFalse(mFolder.create(FolderType.HOLDS_FOLDERS));
- assertFalse(mFolder.create(FolderType.HOLDS_MESSAGES));
-
- // getUnreadMessageCount() always returns -1
- assertEquals(-1, mFolder.getUnreadMessageCount());
-
- // getMessages(MessageRetrievalListener listener) is unsupported
- try {
- mFolder.getMessages(null);
- fail("Exception not thrown by getMessages()");
- } catch (UnsupportedOperationException e) {
- // expected - succeed
- }
-
- // getMessages(String[] uids, MessageRetrievalListener listener) is unsupported
- try {
- mFolder.getMessages(null, null);
- fail("Exception not thrown by getMessages()");
- } catch (UnsupportedOperationException e) {
- // expected - succeed
- }
-
- // getPermanentFlags() returns { Flag.DELETED }
- Flag[] flags = mFolder.getPermanentFlags();
- assertEquals(1, flags.length);
- assertEquals(Flag.DELETED, flags[0]);
-
- // appendMessages(Message[] messages) does nothing
- mFolder.appendMessages(null);
-
- // delete(boolean recurse) does nothing
- // TODO - it should!
- mFolder.delete(false);
-
- // expunge() returns null
- assertNull(mFolder.expunge());
-
- // copyMessages() is unsupported
- try {
- mFolder.copyMessages(null, null);
- fail("Exception not thrown by copyMessages()");
- } catch (UnsupportedOperationException e) {
- // expected - succeed
- }
- }
-
- /**
- * Test the process of opening and indexing a mailbox with one unread message in it.
- *
- * TODO should create an instrumented listener to confirm all expected callbacks. Then use
- * it everywhere we could have passed a message listener.
- */
- public void testOneUnread() throws MessagingException {
-
- MockTransport mockTransport = openAndInjectMockTransport();
-
- checkOneUnread(mockTransport);
- }
-
- /**
- * Test the scenario where the transport is "open" but not really (e.g. server closed). Two
- * things should happen: We should see an intermediate failure that makes sense, and the next
- * operation should reopen properly.
- *
- * There are multiple versions of this test because we are simulating the steps of
- * MessagingController.synchronizeMailboxSyncronous() and we will inject the failure a bit
- * further along in each case, to test various recovery points.
- *
- * This test confirms that Pop3Store needs to call close() in the IOExceptionHandler in
- * Pop3Folder.getMessages().
- */
- public void testCatchClosed1() throws MessagingException {
-
- MockTransport mockTransport = openAndInjectMockTransport();
-
- openFolderWithMessage(mockTransport);
-
- // cause the next sequence to fail on the readLine() calls
- mockTransport.closeInputStream();
-
- // index the message(s) - it should fail, because our stream is broken
- try {
- setupUidlSequence(mockTransport, 1);
- Message[] messages = mFolder.getMessages(1, 1, null);
- assertEquals(1, messages.length);
- assertEquals(getSingleMessageUID(1), messages[0].getUid());
- fail("Broken stream should cause getMessages() to throw.");
- }
- catch(MessagingException me) {
- // success
- }
-
- // At this point the UI would display connection error, which is fine. Now, the real
- // test is, can we recover? So I'll just repeat the above steps, without the failure.
- // NOTE: everything from here down is copied from testOneUnread() and should be consolidated
-
- // confirm that we're closed at this point
- assertFalse("folder should be 'closed' after an IOError", mFolder.isOpen());
-
- // and confirm that the next connection will be OK
- checkOneUnread(mockTransport);
- }
-
- /**
- * Test the scenario where the transport is "open" but not really (e.g. server closed). Two
- * things should happen: We should see an intermediate failure that makes sense, and the next
- * operation should reopen properly.
- *
- * There are multiple versions of this test because we are simulating the steps of
- * MessagingController.synchronizeMailboxSyncronous() and we will inject the failure a bit
- * further along in each case, to test various recovery points.
- *
- * This test confirms that Pop3Store needs to call close() in the first IOExceptionHandler in
- * Pop3Folder.fetch(), for a failure in the call to indexUids().
- */
- public void testCatchClosed2() throws MessagingException {
-
- MockTransport mockTransport = openAndInjectMockTransport();
-
- openFolderWithMessage(mockTransport);
-
- // index the message(s)
- setupUidlSequence(mockTransport, 1);
- Message[] messages = mFolder.getMessages(1, 1, null);
- assertEquals(1, messages.length);
- assertEquals(getSingleMessageUID(1), messages[0].getUid());
-
- // cause the next sequence to fail on the readLine() calls
- mockTransport.closeInputStream();
-
- try {
- // try the basic fetch of flags & envelope
- setupListSequence(mockTransport, 1);
- FetchProfile fp = new FetchProfile();
- fp.add(FetchProfile.Item.FLAGS);
- fp.add(FetchProfile.Item.ENVELOPE);
- mFolder.fetch(messages, fp, null);
- assertEquals(PER_MESSAGE_SIZE, messages[0].getSize());
- fail("Broken stream should cause fetch() to throw.");
- }
- catch(MessagingException me) {
- // success
- }
-
- // At this point the UI would display connection error, which is fine. Now, the real
- // test is, can we recover? So I'll just repeat the above steps, without the failure.
- // NOTE: everything from here down is copied from testOneUnread() and should be consolidated
-
- // confirm that we're closed at this point
- assertFalse("folder should be 'closed' after an IOError", mFolder.isOpen());
-
- // and confirm that the next connection will be OK
- checkOneUnread(mockTransport);
- }
-
- /**
- * Test the scenario where the transport is "open" but not really (e.g. server closed). Two
- * things should happen: We should see an intermediate failure that makes sense, and the next
- * operation should reopen properly.
- *
- * There are multiple versions of this test because we have to check additional places where
- * Pop3Store and/or Pop3Folder should be dealing with IOErrors.
- *
- * This test confirms that Pop3Store needs to call close() in the first IOExceptionHandler in
- * Pop3Folder.fetch(), for a failure in the call to fetchEnvelope().
- */
- public void testCatchClosed2a() {
- // TODO cannot write this test until we can inject stream closures mid-sequence
- }
-
- /**
- * Test the scenario where the transport is "open" but not really (e.g. server closed). Two
- * things should happen: We should see an intermediate failure that makes sense, and the next
- * operation should reopen properly.
- *
- * There are multiple versions of this test because we are simulating the steps of
- * MessagingController.synchronizeMailboxSyncronous() and we will inject the failure a bit
- * further along in each case, to test various recovery points.
- *
- * This test confirms that Pop3Store needs to call close() in the second IOExceptionHandler in
- * Pop3Folder.fetch().
- */
- public void testCatchClosed3() throws MessagingException {
-
- MockTransport mockTransport = openAndInjectMockTransport();
-
- openFolderWithMessage(mockTransport);
-
- // index the message(s)
- setupUidlSequence(mockTransport, 1);
- Message[] messages = mFolder.getMessages(1, 1, null);
- assertEquals(1, messages.length);
- assertEquals(getSingleMessageUID(1), messages[0].getUid());
-
- // try the basic fetch of flags & envelope
- setupListSequence(mockTransport, 1);
- FetchProfile fp = new FetchProfile();
- fp.add(FetchProfile.Item.FLAGS);
- fp.add(FetchProfile.Item.ENVELOPE);
- mFolder.fetch(messages, fp, null);
- assertEquals(PER_MESSAGE_SIZE, messages[0].getSize());
-
- // cause the next sequence to fail on the readLine() calls
- mockTransport.closeInputStream();
-
- try {
- // now try fetching the message
- setupSingleMessage(mockTransport, 1, false);
- fp = new FetchProfile();
- fp.add(FetchProfile.Item.BODY);
- mFolder.fetch(messages, fp, null);
- checkFetchedMessage(messages[0], 1, false);
- fail("Broken stream should cause fetch() to throw.");
- }
- catch(MessagingException me) {
- // success
- }
-
- // At this point the UI would display connection error, which is fine. Now, the real
- // test is, can we recover? So I'll just repeat the above steps, without the failure.
- // NOTE: everything from here down is copied from testOneUnread() and should be consolidated
-
- // confirm that we're closed at this point
- assertFalse("folder should be 'closed' after an IOError", mFolder.isOpen());
-
- // and confirm that the next connection will be OK
- checkOneUnread(mockTransport);
- }
-
- /**
- * Test the scenario where the transport is "open" but not really (e.g. server closed). Two
- * things should happen: We should see an intermediate failure that makes sense, and the next
- * operation should reopen properly.
- *
- * There are multiple versions of this test because we have to check additional places where
- * Pop3Store and/or Pop3Folder should be dealing with IOErrors.
- *
- * This test confirms that Pop3Store needs to call close() in the IOExceptionHandler in
- * Pop3Folder.setFlags().
- */
- public void testCatchClosed4() throws MessagingException {
-
- MockTransport mockTransport = openAndInjectMockTransport();
-
- openFolderWithMessage(mockTransport);
-
- // index the message(s)
- setupUidlSequence(mockTransport, 1);
- Message[] messages = mFolder.getMessages(1, 1, null);
- assertEquals(1, messages.length);
- assertEquals(getSingleMessageUID(1), messages[0].getUid());
-
- // cause the next sequence to fail on the readLine() calls
- mockTransport.closeInputStream();
-
- // delete 'em all - should fail because of broken stream
- try {
- mockTransport.expect("DELE 1", "+OK message deleted");
- mFolder.setFlags(messages, new Flag[] { Flag.DELETED }, true);
- fail("Broken stream should cause fetch() to throw.");
- }
- catch(MessagingException me) {
- // success
- }
-
- // At this point the UI would display connection error, which is fine. Now, the real
- // test is, can we recover? So I'll just repeat the above steps, without the failure.
- // NOTE: everything from here down is copied from testOneUnread() and should be consolidated
-
- // confirm that we're closed at this point
- assertFalse("folder should be 'closed' after an IOError", mFolder.isOpen());
-
- // and confirm that the next connection will be OK
- checkOneUnread(mockTransport);
- }
-
- /**
- * Test the scenario where the transport is "open" but not really (e.g. server closed). Two
- * things should happen: We should see an intermediate failure that makes sense, and the next
- * operation should reopen properly.
- *
- * There are multiple versions of this test because we have to check additional places where
- * Pop3Store and/or Pop3Folder should be dealing with IOErrors.
- *
- * This test confirms that Pop3Store needs to call close() in the first IOExceptionHandler in
- * Pop3Folder.open().
- */
- public void testCatchClosed5() {
- // TODO cannot write this test until we can inject stream closures mid-sequence
- }
-
- /**
- * Test the scenario where the transport is "open" but not really (e.g. server closed). Two
- * things should happen: We should see an intermediate failure that makes sense, and the next
- * operation should reopen properly.
- *
- * There are multiple versions of this test because we have to check additional places where
- * Pop3Store and/or Pop3Folder should be dealing with IOErrors.
- *
- * This test confirms that Pop3Store needs to call close() in the second IOExceptionHandler in
- * Pop3Folder.open() (when it calls STAT).
- */
- public void testCatchClosed6() {
- // TODO cannot write this test until we can inject stream closures mid-sequence
- }
-
- /**
- * Given an initialized mock transport, open it and attempt to "read" one unread message from
- * it. This can be used as a basic test of functionality and it should be possible to call this
- * repeatedly (if you close the folder between calls).
- *
- * @param mockTransport the mock transport we're using
- */
- private void checkOneUnread(MockTransport mockTransport) throws MessagingException {
- openFolderWithMessage(mockTransport);
-
- // index the message(s)
- setupUidlSequence(mockTransport, 1);
- Message[] messages = mFolder.getMessages(1, 1, null);
- assertEquals(1, messages.length);
- assertEquals(getSingleMessageUID(1), messages[0].getUid());
-
- // try the basic fetch of flags & envelope
- setupListSequence(mockTransport, 1);
- FetchProfile fp = new FetchProfile();
- fp.add(FetchProfile.Item.FLAGS);
- fp.add(FetchProfile.Item.ENVELOPE);
- mFolder.fetch(messages, fp, null);
- assertEquals(PER_MESSAGE_SIZE, messages[0].getSize());
-
- // now try fetching the message
- setupSingleMessage(mockTransport, 1, false);
- fp = new FetchProfile();
- fp.add(FetchProfile.Item.BODY);
- mFolder.fetch(messages, fp, null);
- checkFetchedMessage(messages[0], 1, false);
- }
-
- /**
- * Set up a basic MockTransport. open it, and inject it into mStore
- */
- private MockTransport openAndInjectMockTransport() {
- // Create mock transport and inject it into the POP3Store that's already set up
- MockTransport mockTransport = new MockTransport();
- mockTransport.setSecurity(Transport.CONNECTION_SECURITY_NONE);
- mStore.setTransport(mockTransport);
- return mockTransport;
- }
-
- /**
- * Open a folder that's preloaded with one unread message.
- *
- * @param mockTransport the mock transport we're using
- */
- private void openFolderWithMessage(MockTransport mockTransport) throws MessagingException {
- // try to open it
- setupOpenFolder(mockTransport, 1, null);
- mFolder.open(OpenMode.READ_ONLY);
-
- // check message count
- assertEquals(1, mFolder.getMessageCount());
- }
-
- /**
- * Look at a fetched message and confirm that it is complete.
- *
- * TODO this needs to be more dynamic, not just hardcoded for empty message #1.
- *
- * @param message the fetched message to be checked
- * @param msgNum the message number
- */
- private void checkFetchedMessage(Message message, int msgNum, boolean body)
- throws MessagingException {
- // check To:
- Address[] to = message.getRecipients(RecipientType.TO);
- assertNotNull(to);
- assertEquals(1, to.length);
- assertEquals("Smith@Registry.Org", to[0].getAddress());
- assertNull(to[0].getPersonal());
-
- // check From:
- Address[] from = message.getFrom();
- assertNotNull(from);
- assertEquals(1, from.length);
- assertEquals("Jones@Registry.Org", from[0].getAddress());
- assertNull(from[0].getPersonal());
-
- // TODO date
-
- // TODO check body (if applicable)
- }
-
- /**
- * Helper which stuffs the mock with enough strings to satisfy a call to Pop3Folder.open()
- *
- * @param mockTransport the mock transport we're using
- * @param statCount the number of messages to indicate in the STAT
- * @param capabilities if non-null, comma-separated list of capabilities
- */
- private void setupOpenFolder(MockTransport mockTransport, int statCount, String capabilities) {
- mockTransport.expect(null, "+OK Hello there from the Mock Transport.");
- if (capabilities == null) {
- mockTransport.expect("CAPA", "-ERR unimplemented");
- } else {
- mockTransport.expect("CAPA", "+OK capabilities follow");
- mockTransport.expect(null, capabilities.split(",")); // one capability per line
- mockTransport.expect(null, "."); // terminated by "."
- }
- mockTransport.expect("USER user", "+OK User name accepted");
- mockTransport.expect("PASS password", "+OK Logged in");
- String stat = "+OK " + Integer.toString(statCount) + " " +
- Integer.toString(PER_MESSAGE_SIZE * statCount);
- mockTransport.expect("STAT", stat);
- }
-
- /**
- * Setup expects for a UIDL on a mailbox with 0 or more messages in it.
- * @param transport The mock transport to preload
- * @param numMessages The number of messages to return from UIDL.
- */
- private static void setupUidlSequence(MockTransport transport, int numMessages) {
- transport.expect("UIDL", "+OK sending UIDL list");
- for (int msgNum = 1; msgNum <= numMessages; ++msgNum) {
- transport.expect(null, Integer.toString(msgNum) + " " + getSingleMessageUID(msgNum));
- }
- transport.expect(null, ".");
- }
-
- /**
- * Setup expects for a LIST on a mailbox with 0 or more messages in it.
- * @param transport The mock transport to preload
- * @param numMessages The number of messages to return from LIST.
- */
- private static void setupListSequence(MockTransport transport, int numMessages) {
- transport.expect("LIST", "+OK sending scan listing");
- for (int msgNum = 1; msgNum <= numMessages; ++msgNum) {
- transport.expect(null, Integer.toString(msgNum) + " " +
- Integer.toString(PER_MESSAGE_SIZE * msgNum));
- }
- transport.expect(null, ".");
- }
-
- /**
- * Setup a single message to be retrieved.
- *
- * Per RFC822 here is a minimal message header:
- * Date: 26 Aug 76 1429 EDT
- * From: Jones@Registry.Org
- * To: Smith@Registry.Org
- *
- * @param transport the mock transport to preload
- * @param msgNum the message number to expect and return
- * @param body if true, a non-empty body will be added
- */
- private static void setupSingleMessage(MockTransport transport, int msgNum, boolean body) {
- transport.expect("RETR " + Integer.toString(msgNum), "+OK message follows");
- transport.expect(null, "Date: 26 Aug 76 1429 EDT");
- transport.expect(null, "From: Jones@Registry.Org");
- transport.expect(null, "To: Smith@Registry.Org");
- transport.expect(null, "");
- transport.expect(null, ".");
- }
-
- /**
- * Generates a simple unique code for each message. Repeatable.
- * @param msgNum The message number
- * @return a string that can be used as the UID
- */
- private static String getSingleMessageUID(int msgNum) {
- final String UID_HEAD = "ABCDEF-";
- final String UID_TAIL = "";
- return UID_HEAD + Integer.toString(msgNum) + UID_TAIL;
- }
-}
diff --git a/tests/src/com/android/email/mail/transport/MailTransportUnitTests.java b/tests/src/com/android/email/mail/transport/MailTransportUnitTests.java
deleted file mode 100644
index 8c3298625..000000000
--- a/tests/src/com/android/email/mail/transport/MailTransportUnitTests.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.transport;
-
-import com.android.email.mail.transport.MailTransport;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-
-/**
- * Simple unit tests for MailSender. Tests here should not attempt any actual connections.
- */
-@SmallTest
-public class MailTransportUnitTests extends AndroidTestCase {
-
- /**
- * Tests of the Uri parsing logic
- */
- public void testUriParsing() throws URISyntaxException {
-
- // Parse with everything in the Uri
- URI uri = new URI("smtp://user:password@server.com:999");
- MailTransport transport = new MailTransport("SMTP");
- transport.setUri(uri, 888);
- assertEquals("server.com", transport.getHost());
- assertEquals(999, transport.getPort());
- String[] userInfoParts = transport.getUserInfoParts();
- assertNotNull(userInfoParts);
- assertEquals("user", userInfoParts[0]);
- assertEquals("password", userInfoParts[1]);
-
- // Parse with no user/password (e.g. anonymous SMTP)
- uri = new URI("smtp://server.com:999");
- transport = new MailTransport("SMTP");
- transport.setUri(uri, 888);
- assertEquals("server.com", transport.getHost());
- assertEquals(999, transport.getPort());
- assertNull(transport.getUserInfoParts());
- }
-}
diff --git a/tests/src/com/android/email/mail/transport/MockTransport.java b/tests/src/com/android/email/mail/transport/MockTransport.java
deleted file mode 100644
index 826444f30..000000000
--- a/tests/src/com/android/email/mail/transport/MockTransport.java
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.transport;
-
-import com.android.email.mail.Transport;
-
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.SocketException;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * This is a mock Transport that is used to test protocols that use MailTransport.
- */
-public class MockTransport implements Transport {
-
- // All flags defining debug or development code settings must be FALSE
- // when code is checked in or released.
- private static boolean DEBUG_LOG_STREAMS = true;
-
- private static String LOG_TAG = "MockTransport";
-
- private boolean mSslAllowed = false;
- private boolean mTlsAllowed = false;
-
- private boolean mOpen;
- private boolean mInputOpen;
- private int mConnectionSecurity;
-
- private ArrayList<String> mQueuedInput = new ArrayList<String>();
-
- private static class Transaction {
- public static final int ACTION_INJECT_TEXT = 0;
- public static final int ACTION_SERVER_CLOSE = 1;
- public static final int ACTION_CLIENT_CLOSE = 2;
-
- int mAction;
- String mPattern;
- String[] mResponses;
-
- Transaction(String pattern, String[] responses) {
- mAction = ACTION_INJECT_TEXT;
- mPattern = pattern;
- mResponses = responses;
- }
-
- Transaction(int otherType) {
- mAction = otherType;
- mPattern = null;
- mResponses = null;
- }
-
- @Override
- public String toString() {
- switch (mAction) {
- case ACTION_INJECT_TEXT:
- return mPattern + ": " + Arrays.toString(mResponses);
- case ACTION_SERVER_CLOSE:
- return "Close the server connection";
- case ACTION_CLIENT_CLOSE:
- return "Expect the client to close";
- default:
- return "(Hmm. Unknown action.)";
- }
- }
- }
-
- private ArrayList<Transaction> mPairs = new ArrayList<Transaction>();
-
- /**
- * Give the mock a pattern to wait for and a response to send back.
- * @param pattern Java RegEx to wait for
- * @param response String to reply with, or null to acccept string but not respond to it
- */
- public void expect(String pattern, String response) {
- expect(pattern, (response == null) ? null : new String[] { response });
- }
-
- /**
- * Give the mock a pattern to wait for and a multi-line response to send back.
- * @param pattern Java RegEx to wait for
- * @param responses Strings to reply with
- */
- public void expect(String pattern, String[] responses) {
- Transaction pair = new Transaction(pattern, responses);
- mPairs.add(pair);
- }
-
- /**
- * Tell the Mock Transport that we expect it to be closed. This will preserve
- * the remaining entries in the expect() stream and allow us to "ride over" the close (which
- * would normally reset everything).
- */
- public void expectClose() {
- mPairs.add(new Transaction(Transaction.ACTION_CLIENT_CLOSE));
- }
-
- private void sendResponse(String[] responses) {
- for (String s : responses) {
- mQueuedInput.add(s);
- }
- }
-
- public boolean canTrySslSecurity() {
- return (mConnectionSecurity == CONNECTION_SECURITY_SSL_REQUIRED
- || mConnectionSecurity == CONNECTION_SECURITY_SSL_OPTIONAL);
- }
-
- public boolean canTryTlsSecurity() {
- return (mConnectionSecurity == Transport.CONNECTION_SECURITY_TLS_OPTIONAL
- || mConnectionSecurity == Transport.CONNECTION_SECURITY_TLS_REQUIRED);
- }
-
- /**
- * This simulates a condition where the server has closed its side, causing
- * reads to fail.
- */
- public void closeInputStream() {
- mInputOpen = false;
- }
-
- public void close() {
- mOpen = false;
- mInputOpen = false;
- // unless it was expected as part of a test, reset the stream
- if (mPairs.size() > 0) {
- Transaction expect = mPairs.remove(0);
- if (expect.mAction == Transaction.ACTION_CLIENT_CLOSE) {
- return;
- }
- }
- mQueuedInput.clear();
- mPairs.clear();
- }
-
- public String getHost() {
- SmtpSenderUnitTests.fail("getHost() not implemented");
- return null;
- }
-
- public InputStream getInputStream() {
- SmtpSenderUnitTests.assertTrue(mOpen);
- return new MockInputStream();
- }
-
- /**
- * This normally serves as a pseudo-clone, for use by Imap. For the purposes of unit testing,
- * until we need something more complex, we'll just return the actual MockTransport. Then we
- * don't have to worry about dealing with test metadata like the expects list or socket state.
- */
- public Transport newInstanceWithConfiguration() {
- return this;
- }
-
- public OutputStream getOutputStream() {
- SmtpSenderUnitTests.assertTrue(mOpen);
- return new MockOutputStream();
- }
-
- public int getPort() {
- SmtpSenderUnitTests.fail("getPort() not implemented");
- return 0;
- }
-
- public int getSecurity() {
- return mConnectionSecurity;
- }
-
- public String[] getUserInfoParts() {
- SmtpSenderUnitTests.fail("getUserInfoParts() not implemented");
- return null;
- }
-
- public boolean isOpen() {
- return mOpen;
- }
-
- public void open() /* throws MessagingException, CertificateValidationException */ {
- mOpen = true;
- mInputOpen = true;
- }
-
- /**
- * This returns one string (if available) to the caller. Usually this simply pulls strings
- * from the mQueuedInput list, but if the list is empty, we also peek the expect list. This
- * supports banners, multi-line responses, and any other cases where we respond without
- * a specific expect pattern.
- *
- * If no response text is available, we assert (failing our test) as an underflow.
- *
- * Logs the read text if DEBUG_LOG_STREAMS is true.
- */
- public String readLine() throws IOException {
- SmtpSenderUnitTests.assertTrue(mOpen);
- if (!mInputOpen) {
- throw new IOException("Reading from MockTransport with closed input");
- }
- // if there's nothing to read, see if we can find a null-pattern response
- if (0 == mQueuedInput.size()) {
- Transaction pair = mPairs.get(0);
- if (pair != null && pair.mPattern == null) {
- mPairs.remove(0);
- sendResponse(pair.mResponses);
- }
- }
- SmtpSenderUnitTests.assertTrue("Underflow reading from MockTransport", 0 != mQueuedInput.size());
- String line = mQueuedInput.remove(0);
- if (DEBUG_LOG_STREAMS) {
- Log.d(LOG_TAG, "<<< " + line);
- }
- return line;
- }
-
- public void reopenTls() /* throws MessagingException */ {
- SmtpSenderUnitTests.assertTrue(mOpen);
- SmtpSenderUnitTests.assertTrue(mTlsAllowed);
- SmtpSenderUnitTests.fail("reopenTls() not implemented");
- }
-
- public void setSecurity(int connectionSecurity) {
- mConnectionSecurity = connectionSecurity;
- }
-
- public void setSoTimeout(int timeoutMilliseconds) /* throws SocketException */ {
- }
-
- public void setUri(URI uri, int defaultPort) {
- SmtpSenderUnitTests.assertTrue("Don't call setUri on a mock transport", false);
- }
-
- /**
- * Accepts a single string (command or text) that was written by the code under test.
- * Because we are essentially mocking a server, we check to see if this string was expected.
- * If the string was expected, we push the corresponding responses into the mQueuedInput
- * list, for subsequent calls to readLine(). If the string does not match, we assert
- * the mismatch. If no string was expected, we assert it as an overflow.
- *
- * Logs the written text if DEBUG_LOG_STREAMS is true.
- */
- public void writeLine(String s, String sensitiveReplacement) /* throws IOException */ {
- if (DEBUG_LOG_STREAMS) {
- Log.d(LOG_TAG, ">>> " + s);
- }
- SmtpSenderUnitTests.assertTrue(mOpen);
- SmtpSenderUnitTests.assertTrue("Overflow writing to MockTransport", 0 != mPairs.size());
- Transaction pair = mPairs.remove(0);
- SmtpSenderUnitTests.assertTrue("Unexpected string written to MockTransport",
- pair.mPattern != null && s.matches(pair.mPattern));
- if (pair.mResponses != null) {
- sendResponse(pair.mResponses);
- }
- }
-
- /**
- * This is an InputStream that satisfies the needs of getInputStream()
- */
- private class MockInputStream extends InputStream {
-
- byte[] mNextLine = null;
- int mNextIndex = 0;
-
- /**
- * Reads from the same input buffer as readLine()
- */
- @Override
- public int read() throws IOException {
- if (!mInputOpen) {
- throw new IOException();
- }
-
- if (mNextLine != null && mNextIndex < mNextLine.length) {
- return mNextLine[mNextIndex++];
- }
-
- // previous line was exhausted so try to get another one
- String next = readLine();
- if (next == null) {
- throw new IOException("Reading from MockTransport with closed input");
- }
- mNextLine = (next + "\r\n").getBytes();
- mNextIndex = 0;
-
- if (mNextLine != null && mNextIndex < mNextLine.length) {
- return mNextLine[mNextIndex++];
- }
-
- // no joy - throw an exception
- throw new IOException();
- }
- }
-
- /**
- * This is an OutputStream that satisfies the needs of getOutputStream()
- */
- private class MockOutputStream extends OutputStream {
-
- StringBuilder sb = new StringBuilder();
-
- @Override
- public void write(int oneByte) throws IOException {
- switch (oneByte) {
- case '\n':
- case '\r':
- if (sb.length() > 0) {
- writeLine(sb.toString(), null);
- sb = new StringBuilder();
- }
- break;
- default:
- sb.append((char)oneByte);
- }
- }
- }
-} \ No newline at end of file
diff --git a/tests/src/com/android/email/mail/transport/SmtpSenderUnitTests.java b/tests/src/com/android/email/mail/transport/SmtpSenderUnitTests.java
deleted file mode 100644
index fee35af1e..000000000
--- a/tests/src/com/android/email/mail/transport/SmtpSenderUnitTests.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.transport;
-
-import com.android.email.mail.Address;
-import com.android.email.mail.MessagingException;
-import com.android.email.mail.Transport;
-import com.android.email.mail.Message.RecipientType;
-import com.android.email.mail.internet.MimeMessage;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import java.util.Date;
-
-/**
- * This is a series of unit tests for the SMTP Sender class. These tests must be locally
- * complete - no server(s) required.
- */
-@SmallTest
-public class SmtpSenderUnitTests extends AndroidTestCase {
-
- /* These values are provided by setUp() */
- private SmtpSender mSender = null;
-
- /**
- * Setup code. We generate a lightweight SmtpSender for testing.
- */
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- // These are needed so we can get at the inner classes
- mSender = new SmtpSender("smtp://user:password@server:999");
- }
-
- /**
- * Confirms simple non-SSL non-TLS login
- */
- public void testSimpleLogin() throws MessagingException {
-
- MockTransport mockTransport = openAndInjectMockTransport();
-
- // try to open it
- setupOpen(mockTransport, null);
- mSender.open();
- }
-
- /**
- * TODO: Test with SSL negotiation (faked)
- * TODO: Test with SSL required but not supported
- * TODO: Test with TLS negotiation (faked)
- * TODO: Test with TLS required but not supported
- * TODO: Test other capabilities.
- * TODO: Test AUTH LOGIN
- */
-
- /**
- * Test: Open and send a single message (sunny day)
- *
- * Note: The final expect (for the ".") is a bit awkward because SmtpSender transmits the
- * final line as "\r\n." instead of "" and ".".
- */
- public void testSendSingleMessage() throws MessagingException {
- MockTransport mockTransport = openAndInjectMockTransport();
-
- // Since SmtpSender.sendMessage() does a close then open, we need to preset for the open
- mockTransport.expectClose();
- setupOpen(mockTransport, null);
-
- // prepare and send a really simple message
- MimeMessage message = new MimeMessage();
- // TODO use a fixed date for these tests
- message.setSentDate(new Date());
- Address from = new Address("Jones@Registry.Org", null);
- Address to = new Address("Smith@Registry.Org", null);
- message.setFrom(from);
- message.setRecipients(RecipientType.TO, new Address[] { to });
-
- // prepare for the message traffic we'll see
- // TODO We should have a method to do this for any Message
- mockTransport.expect("MAIL FROM: <Jones@Registry.Org>",
- "250 2.1.0 <Jones@Registry.Org> sender ok");
- mockTransport.expect("RCPT TO: <Smith@Registry.Org>",
- "250 2.1.5 <Smith@Registry.Org> recipient ok");
- mockTransport.expect("DATA", "354 enter mail, end with . on a line by itself");
- mockTransport.expect("Message-ID: .*", (String)null);
- mockTransport.expect("Date: .*", (String)null);
- mockTransport.expect("From: Jones@Registry.Org", (String)null);
- mockTransport.expect("To: Smith@Registry.Org", (String)null);
- mockTransport.expect("\r\n\\.", "250 2.0.0 kv2f1a00C02Rf8w3Vv mail accepted for delivery");
-
- // Now trigger the transmission
- mSender.sendMessage(message);
- }
-
- /**
- * Set up a basic MockTransport. open it, and inject it into mStore
- */
- private MockTransport openAndInjectMockTransport() {
- // Create mock transport and inject it into the SmtpSender that's already set up
- MockTransport mockTransport = new MockTransport();
- mockTransport.setSecurity(Transport.CONNECTION_SECURITY_NONE);
- mSender.setTransport(mockTransport);
- return mockTransport;
- }
-
- /**
- * Helper which stuffs the mock with enough strings to satisfy a call to SmtpSender.open()
- *
- * @param mockTransport the mock transport we're using
- * @param capabilities if non-null, comma-separated list of capabilities
- */
- private void setupOpen(MockTransport mockTransport, String capabilities) {
- mockTransport.expect(null, "220 MockTransport 2000 Ready To Assist You Peewee");
- mockTransport.expect("EHLO .*", "250-10.20.30.40 hello");
- if (capabilities == null) {
- mockTransport.expect(null, "250-HELP");
- mockTransport.expect(null, "250-AUTH LOGIN PLAIN CRAM-MD5");
- mockTransport.expect(null, "250-SIZE 15728640");
- mockTransport.expect(null, "250-ENHANCEDSTATUSCODES");
- mockTransport.expect(null, "250-8BITMIME");
- } else {
- for (String capability : capabilities.split(",")) {
- mockTransport.expect(null, "250-" + capability);
- }
- }
- mockTransport.expect(null, "250+OK");
- mockTransport.expect("AUTH PLAIN .*", "235 2.7.0 ... authentication succeeded");
- }
-}